1 1.25 christos /* $NetBSD: query.c,v 1.26 2026/01/29 18:37:56 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.15 christos * SPDX-License-Identifier: MPL-2.0 7 1.15 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.11 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos /*! \file */ 17 1.1 christos 18 1.14 christos #include <ctype.h> 19 1.3 christos #include <inttypes.h> 20 1.3 christos #include <stdbool.h> 21 1.23 christos #include <stdint.h> 22 1.1 christos #include <string.h> 23 1.1 christos 24 1.23 christos #include <isc/async.h> 25 1.26 christos #include <isc/atomic.h> 26 1.24 christos #include <isc/counter.h> 27 1.1 christos #include <isc/hex.h> 28 1.1 christos #include <isc/mem.h> 29 1.9 christos #include <isc/once.h> 30 1.1 christos #include <isc/random.h> 31 1.20 christos #include <isc/result.h> 32 1.1 christos #include <isc/rwlock.h> 33 1.1 christos #include <isc/serial.h> 34 1.1 christos #include <isc/stats.h> 35 1.1 christos #include <isc/string.h> 36 1.1 christos #include <isc/thread.h> 37 1.1 christos #include <isc/util.h> 38 1.1 christos 39 1.1 christos #include <dns/adb.h> 40 1.1 christos #include <dns/badcache.h> 41 1.1 christos #include <dns/byaddr.h> 42 1.1 christos #include <dns/cache.h> 43 1.1 christos #include <dns/db.h> 44 1.1 christos #include <dns/dlz.h> 45 1.1 christos #include <dns/dns64.h> 46 1.1 christos #include <dns/dnsrps.h> 47 1.1 christos #include <dns/dnssec.h> 48 1.24 christos #include <dns/ede.h> 49 1.1 christos #include <dns/keytable.h> 50 1.1 christos #include <dns/message.h> 51 1.1 christos #include <dns/ncache.h> 52 1.1 christos #include <dns/nsec.h> 53 1.1 christos #include <dns/nsec3.h> 54 1.1 christos #include <dns/order.h> 55 1.20 christos #include <dns/rbt.h> 56 1.23 christos #include <dns/rcode.h> 57 1.1 christos #include <dns/rdata.h> 58 1.1 christos #include <dns/rdataclass.h> 59 1.1 christos #include <dns/rdatalist.h> 60 1.1 christos #include <dns/rdataset.h> 61 1.1 christos #include <dns/rdatasetiter.h> 62 1.1 christos #include <dns/rdatastruct.h> 63 1.1 christos #include <dns/rdatatype.h> 64 1.1 christos #include <dns/resolver.h> 65 1.1 christos #include <dns/result.h> 66 1.1 christos #include <dns/stats.h> 67 1.1 christos #include <dns/tkey.h> 68 1.1 christos #include <dns/types.h> 69 1.1 christos #include <dns/view.h> 70 1.1 christos #include <dns/zone.h> 71 1.1 christos #include <dns/zt.h> 72 1.1 christos 73 1.1 christos #include <ns/client.h> 74 1.9 christos #include <ns/hooks.h> 75 1.1 christos #include <ns/interfacemgr.h> 76 1.1 christos #include <ns/log.h> 77 1.1 christos #include <ns/server.h> 78 1.1 christos #include <ns/sortlist.h> 79 1.1 christos #include <ns/stats.h> 80 1.1 christos #include <ns/xfrout.h> 81 1.1 christos 82 1.23 christos #include "probes.h" 83 1.7 christos 84 1.1 christos #if 0 85 1.1 christos /* 86 1.1 christos * It has been recommended that DNS64 be changed to return excluded 87 1.1 christos * AAAA addresses if DNS64 synthesis does not occur. This minimises 88 1.1 christos * the impact on the lookup results. While most DNS AAAA lookups are 89 1.1 christos * done to send IP packets to a host, not all of them are and filtering 90 1.1 christos * excluded addresses has a negative impact on those uses. 91 1.1 christos */ 92 1.1 christos #define dns64_bis_return_excluded_addresses 1 93 1.9 christos #endif /* if 0 */ 94 1.1 christos 95 1.11 christos #define QUERY_ERROR(qctx, r) \ 96 1.11 christos do { \ 97 1.11 christos (qctx)->result = r; \ 98 1.11 christos (qctx)->want_restart = false; \ 99 1.11 christos (qctx)->line = __LINE__; \ 100 1.12 rillig } while (0) 101 1.1 christos 102 1.1 christos /*% Partial answer? */ 103 1.9 christos #define PARTIALANSWER(c) \ 104 1.9 christos (((c)->query.attributes & NS_QUERYATTR_PARTIALANSWER) != 0) 105 1.1 christos /*% Use Cache? */ 106 1.9 christos #define USECACHE(c) (((c)->query.attributes & NS_QUERYATTR_CACHEOK) != 0) 107 1.1 christos /*% Recursion OK? */ 108 1.9 christos #define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0) 109 1.1 christos /*% Recursing? */ 110 1.9 christos #define RECURSING(c) (((c)->query.attributes & NS_QUERYATTR_RECURSING) != 0) 111 1.1 christos /*% Want Recursion? */ 112 1.9 christos #define WANTRECURSION(c) \ 113 1.9 christos (((c)->query.attributes & NS_QUERYATTR_WANTRECURSION) != 0) 114 1.1 christos /*% Is TCP? */ 115 1.9 christos #define TCP(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0) 116 1.1 christos 117 1.1 christos /*% Want DNSSEC? */ 118 1.9 christos #define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) 119 1.1 christos /*% Want WANTAD? */ 120 1.9 christos #define WANTAD(c) (((c)->attributes & NS_CLIENTATTR_WANTAD) != 0) 121 1.23 christos /*% Client presented a bad COOKIE. */ 122 1.23 christos #define BADCOOKIE(c) (((c)->attributes & NS_CLIENTATTR_BADCOOKIE) != 0) 123 1.1 christos /*% Client presented a valid COOKIE. */ 124 1.9 christos #define HAVECOOKIE(c) (((c)->attributes & NS_CLIENTATTR_HAVECOOKIE) != 0) 125 1.1 christos /*% Client presented a COOKIE. */ 126 1.9 christos #define WANTCOOKIE(c) (((c)->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0) 127 1.1 christos /*% Client presented a CLIENT-SUBNET option. */ 128 1.9 christos #define HAVEECS(c) (((c)->attributes & NS_CLIENTATTR_HAVEECS) != 0) 129 1.1 christos /*% No authority? */ 130 1.9 christos #define NOAUTHORITY(c) (((c)->query.attributes & NS_QUERYATTR_NOAUTHORITY) != 0) 131 1.1 christos /*% No additional? */ 132 1.9 christos #define NOADDITIONAL(c) \ 133 1.9 christos (((c)->query.attributes & NS_QUERYATTR_NOADDITIONAL) != 0) 134 1.1 christos /*% Secure? */ 135 1.9 christos #define SECURE(c) (((c)->query.attributes & NS_QUERYATTR_SECURE) != 0) 136 1.1 christos /*% DNS64 A lookup? */ 137 1.9 christos #define DNS64(c) (((c)->query.attributes & NS_QUERYATTR_DNS64) != 0) 138 1.1 christos 139 1.9 christos #define DNS64EXCLUDE(c) \ 140 1.9 christos (((c)->query.attributes & NS_QUERYATTR_DNS64EXCLUDE) != 0) 141 1.1 christos 142 1.9 christos #define REDIRECT(c) (((c)->query.attributes & NS_QUERYATTR_REDIRECT) != 0) 143 1.1 christos 144 1.14 christos /*% Was the client already sent a response? */ 145 1.11 christos #define QUERY_ANSWERED(q) (((q)->attributes & NS_QUERYATTR_ANSWERED) != 0) 146 1.11 christos 147 1.13 christos /*% Does the query wants to check for stale RRset due to a timeout? */ 148 1.13 christos #define QUERY_STALETIMEOUT(q) (((q)->dboptions & DNS_DBFIND_STALETIMEOUT) != 0) 149 1.11 christos 150 1.1 christos /*% Does the rdataset 'r' have an attached 'No QNAME Proof'? */ 151 1.9 christos #define NOQNAME(r) (((r)->attributes & DNS_RDATASETATTR_NOQNAME) != 0) 152 1.1 christos 153 1.4 christos /*% Does the rdataset 'r' contain a stale answer? */ 154 1.9 christos #define STALE(r) (((r)->attributes & DNS_RDATASETATTR_STALE) != 0) 155 1.1 christos 156 1.11 christos /*% Does the rdataset 'r' is stale and within stale-refresh-time? */ 157 1.11 christos #define STALE_WINDOW(r) (((r)->attributes & DNS_RDATASETATTR_STALE_WINDOW) != 0) 158 1.11 christos 159 1.1 christos #ifdef WANT_QUERYTRACE 160 1.15 christos static void 161 1.1 christos client_trace(ns_client_t *client, int level, const char *message) { 162 1.1 christos if (client != NULL && client->query.qname != NULL) { 163 1.1 christos if (isc_log_wouldlog(ns_lctx, level)) { 164 1.1 christos char qbuf[DNS_NAME_FORMATSIZE]; 165 1.1 christos char tbuf[DNS_RDATATYPE_FORMATSIZE]; 166 1.9 christos dns_name_format(client->query.qname, qbuf, 167 1.9 christos sizeof(qbuf)); 168 1.9 christos dns_rdatatype_format(client->query.qtype, tbuf, 169 1.9 christos sizeof(tbuf)); 170 1.9 christos isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, 171 1.1 christos NS_LOGMODULE_QUERY, level, 172 1.13 christos "query client=%p thread=0x%" PRIxPTR 173 1.1 christos "(%s/%s): %s", 174 1.13 christos client, isc_thread_self(), qbuf, tbuf, 175 1.13 christos message); 176 1.1 christos } 177 1.9 christos } else { 178 1.9 christos isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, 179 1.1 christos NS_LOGMODULE_QUERY, level, 180 1.13 christos "query client=%p thread=0x%" PRIxPTR 181 1.1 christos "(<unknown-query>): %s", 182 1.13 christos client, isc_thread_self(), message); 183 1.1 christos } 184 1.1 christos } 185 1.9 christos #define CTRACE(l, m) client_trace(client, l, m) 186 1.9 christos #define CCTRACE(l, m) client_trace(qctx->client, l, m) 187 1.9 christos #else /* ifdef WANT_QUERYTRACE */ 188 1.9 christos #define CTRACE(l, m) ((void)m) 189 1.9 christos #define CCTRACE(l, m) ((void)m) 190 1.1 christos #endif /* WANT_QUERYTRACE */ 191 1.1 christos 192 1.20 christos #define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0) 193 1.1 christos 194 1.1 christos #define SFCACHE_CDFLAG 0x1 195 1.1 christos 196 1.1 christos /* 197 1.20 christos * SAVE and RESTORE have the same semantics as: 198 1.1 christos * 199 1.20 christos * foo_attach(b, &a); 200 1.20 christos * foo_detach(&b); 201 1.1 christos * 202 1.1 christos * without the locking and magic testing. 203 1.1 christos * 204 1.20 christos * We use the names SAVE and RESTORE to show the operation being performed, 205 1.20 christos * even though the two macros are identical. 206 1.1 christos */ 207 1.9 christos #define SAVE(a, b) \ 208 1.9 christos do { \ 209 1.9 christos INSIST(a == NULL); \ 210 1.9 christos a = b; \ 211 1.9 christos b = NULL; \ 212 1.12 rillig } while (0) 213 1.1 christos #define RESTORE(a, b) SAVE(a, b) 214 1.1 christos 215 1.26 christos static atomic_uint_fast32_t last_rpznotready_log = 0; 216 1.26 christos 217 1.26 christos static bool 218 1.26 christos can_log_rpznotready(void) { 219 1.26 christos isc_stdtime_t last; 220 1.26 christos isc_stdtime_t now = isc_stdtime_now(); 221 1.26 christos last = atomic_exchange_relaxed(&last_rpznotready_log, now); 222 1.26 christos if (now != last) { 223 1.26 christos return true; 224 1.26 christos } 225 1.26 christos 226 1.26 christos return false; 227 1.26 christos } 228 1.26 christos 229 1.3 christos static bool 230 1.1 christos validate(ns_client_t *client, dns_db_t *db, dns_name_t *name, 231 1.1 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); 232 1.1 christos 233 1.1 christos static void 234 1.1 christos query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, 235 1.1 christos dns_dbversion_t *version, ns_client_t *client, 236 1.1 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 237 1.9 christos dns_name_t *fname, bool exact, dns_name_t *found); 238 1.1 christos 239 1.15 christos static void 240 1.1 christos log_queryerror(ns_client_t *client, isc_result_t result, int line, int level); 241 1.1 christos 242 1.1 christos static void 243 1.1 christos rpz_st_clear(ns_client_t *client); 244 1.1 christos 245 1.3 christos static bool 246 1.1 christos rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult, 247 1.1 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); 248 1.1 christos 249 1.1 christos static void 250 1.1 christos log_noexistnodata(void *val, int level, const char *fmt, ...) 251 1.1 christos ISC_FORMAT_PRINTF(3, 4); 252 1.1 christos 253 1.20 christos static isc_result_t 254 1.20 christos query_addanswer(query_ctx_t *qctx); 255 1.20 christos 256 1.20 christos static isc_result_t 257 1.20 christos query_prepare_delegation_response(query_ctx_t *qctx); 258 1.20 christos 259 1.23 christos static isc_result_t 260 1.23 christos acquire_recursionquota(ns_client_t *client); 261 1.23 christos 262 1.23 christos static void 263 1.23 christos release_recursionquota(ns_client_t *client); 264 1.23 christos 265 1.3 christos /* 266 1.3 christos * Return the hooktable in use with 'qctx', or if there isn't one 267 1.3 christos * set, return the default hooktable. 268 1.3 christos */ 269 1.15 christos static ns_hooktable_t * 270 1.3 christos get_hooktab(query_ctx_t *qctx) { 271 1.9 christos if (qctx == NULL || qctx->view == NULL || qctx->view->hooktable == NULL) 272 1.3 christos { 273 1.23 christos return ns__hook_table; 274 1.3 christos } 275 1.1 christos 276 1.23 christos return qctx->view->hooktable; 277 1.3 christos } 278 1.1 christos 279 1.3 christos /* 280 1.3 christos * Call the specified hook function in every configured module that implements 281 1.3 christos * that function. If any hook function returns NS_HOOK_RETURN, we 282 1.3 christos * set 'result' and terminate processing by jumping to the 'cleanup' tag. 283 1.3 christos * 284 1.3 christos * (Note that a hook function may set the 'result' to ISC_R_SUCCESS but 285 1.3 christos * still terminate processing within the calling function. That's why this 286 1.15 christos * is a macro instead of a static function; it needs to be able to use 287 1.3 christos * 'goto cleanup' regardless of the return value.) 288 1.3 christos */ 289 1.9 christos #define CALL_HOOK(_id, _qctx) \ 290 1.9 christos do { \ 291 1.20 christos isc_result_t _res = result; \ 292 1.9 christos ns_hooktable_t *_tab = get_hooktab(_qctx); \ 293 1.9 christos ns_hook_t *_hook; \ 294 1.9 christos _hook = ISC_LIST_HEAD((*_tab)[_id]); \ 295 1.9 christos while (_hook != NULL) { \ 296 1.9 christos ns_hook_action_t _func = _hook->action; \ 297 1.9 christos void *_data = _hook->action_data; \ 298 1.9 christos INSIST(_func != NULL); \ 299 1.9 christos switch (_func(_qctx, _data, &_res)) { \ 300 1.9 christos case NS_HOOK_CONTINUE: \ 301 1.9 christos _hook = ISC_LIST_NEXT(_hook, link); \ 302 1.9 christos break; \ 303 1.9 christos case NS_HOOK_RETURN: \ 304 1.9 christos result = _res; \ 305 1.9 christos goto cleanup; \ 306 1.9 christos default: \ 307 1.15 christos UNREACHABLE(); \ 308 1.9 christos } \ 309 1.9 christos } \ 310 1.3 christos } while (false) 311 1.1 christos 312 1.3 christos /* 313 1.3 christos * Call the specified hook function in every configured module that 314 1.3 christos * implements that function. All modules are called; hook function return 315 1.3 christos * codes are ignored. This is intended for use with initialization and 316 1.3 christos * destruction calls which *must* run in every configured module. 317 1.3 christos * 318 1.15 christos * (This could be implemented as a static void function, but is left as a 319 1.3 christos * macro for symmetry with CALL_HOOK above.) 320 1.3 christos */ 321 1.9 christos #define CALL_HOOK_NORETURN(_id, _qctx) \ 322 1.9 christos do { \ 323 1.9 christos isc_result_t _res; \ 324 1.9 christos ns_hooktable_t *_tab = get_hooktab(_qctx); \ 325 1.9 christos ns_hook_t *_hook; \ 326 1.9 christos _hook = ISC_LIST_HEAD((*_tab)[_id]); \ 327 1.9 christos while (_hook != NULL) { \ 328 1.9 christos ns_hook_action_t _func = _hook->action; \ 329 1.9 christos void *_data = _hook->action_data; \ 330 1.9 christos INSIST(_func != NULL); \ 331 1.9 christos _func(_qctx, _data, &_res); \ 332 1.9 christos _hook = ISC_LIST_NEXT(_hook, link); \ 333 1.9 christos } \ 334 1.3 christos } while (false) 335 1.1 christos 336 1.1 christos /* 337 1.1 christos * The functions defined below implement the query logic that previously lived 338 1.1 christos * in the single very complex function query_find(). The query_ctx_t structure 339 1.1 christos * defined in <ns/query.h> maintains state from function to function. The call 340 1.1 christos * flow for the general query processing algorithm is described below: 341 1.1 christos * 342 1.1 christos * 1. Set up query context and other resources for a client 343 1.1 christos * query (query_setup()) 344 1.1 christos * 345 1.1 christos * 2. Start the search (ns__query_start()) 346 1.1 christos * 347 1.1 christos * 3. Identify authoritative data sources which may have an answer; 348 1.1 christos * search them (query_lookup()). If an answer is found, go to 7. 349 1.1 christos * 350 1.1 christos * 4. If recursion or cache access are allowed, search the cache 351 1.1 christos * (query_lookup() again, using the cache database) to find a better 352 1.1 christos * answer. If an answer is found, go to 7. 353 1.1 christos * 354 1.3 christos * 5. If recursion is allowed, begin recursion (ns_query_recurse()). 355 1.1 christos * Go to 15 to clean up this phase of the query. When recursion 356 1.1 christos * is complete, processing will resume at 6. 357 1.1 christos * 358 1.1 christos * 6. Resume from recursion; set up query context for resumed processing. 359 1.1 christos * 360 1.1 christos * 7. Determine what sort of answer we've found (query_gotanswer()) 361 1.1 christos * and call other functions accordingly: 362 1.1 christos * - not found (auth or cache), go to 8 363 1.1 christos * - delegation, go to 9 364 1.1 christos * - no such domain (auth), go to 10 365 1.1 christos * - empty answer (auth), go to 11 366 1.1 christos * - negative response (cache), go to 12 367 1.1 christos * - answer found, go to 13 368 1.1 christos * 369 1.1 christos * 8. The answer was not found in the database (query_notfound(). 370 1.1 christos * Set up a referral and go to 9. 371 1.1 christos * 372 1.3 christos * 9. Handle a delegation response (query_delegation()). If we need 373 1.3 christos * to and are allowed to recurse (query_delegation_recurse()), go to 5, 374 1.3 christos * otherwise go to 15 to clean up and return the delegation to the client. 375 1.1 christos * 376 1.1 christos * 10. No such domain (query_nxdomain()). Attempt redirection; if 377 1.1 christos * unsuccessful, add authority section records (query_addsoa(), 378 1.1 christos * query_addauth()), then go to 15 to return NXDOMAIN to client. 379 1.1 christos * 380 1.1 christos * 11. Empty answer (query_nodata()). Add authority section records 381 1.1 christos * (query_addsoa(), query_addauth()) and signatures if authoritative 382 1.1 christos * (query_sign_nodata()) then go to 15 and return 383 1.1 christos * NOERROR/ANCOUNT=0 to client. 384 1.1 christos * 385 1.1 christos * 12. No such domain or empty answer returned from cache (query_ncache()). 386 1.1 christos * Set response code appropriately, go to 11. 387 1.1 christos * 388 1.1 christos * 13. Prepare a response (query_prepresponse()) and then fill it 389 1.1 christos * appropriately (query_respond(), or for type ANY, 390 1.1 christos * query_respond_any()). 391 1.1 christos * 392 1.1 christos * 14. If a restart is needed due to CNAME/DNAME chaining, go to 2. 393 1.1 christos * 394 1.1 christos * 15. Clean up resources. If recursing, stop and wait for the event 395 1.1 christos * handler to be called back (step 6). If an answer is ready, 396 1.1 christos * return it to the client. 397 1.1 christos * 398 1.1 christos * (XXX: This description omits several special cases including 399 1.3 christos * DNS64, RPZ, RRL, and the SERVFAIL cache. It also doesn't discuss 400 1.3 christos * plugins.) 401 1.1 christos */ 402 1.1 christos 403 1.1 christos static void 404 1.1 christos query_trace(query_ctx_t *qctx); 405 1.1 christos 406 1.1 christos static void 407 1.23 christos qctx_init(ns_client_t *client, dns_fetchresponse_t **respp, 408 1.23 christos dns_rdatatype_t qtype, query_ctx_t *qctx); 409 1.1 christos 410 1.1 christos static isc_result_t 411 1.23 christos qctx_prepare_buffers(query_ctx_t *qctx, isc_buffer_t *buffer); 412 1.23 christos 413 1.23 christos static void 414 1.23 christos qctx_freedata(query_ctx_t *qctx); 415 1.23 christos 416 1.23 christos static void 417 1.23 christos qctx_destroy(query_ctx_t *qctx); 418 1.23 christos 419 1.23 christos static void 420 1.1 christos query_setup(ns_client_t *client, dns_rdatatype_t qtype); 421 1.1 christos 422 1.1 christos static isc_result_t 423 1.1 christos query_lookup(query_ctx_t *qctx); 424 1.1 christos 425 1.1 christos static void 426 1.23 christos fetch_callback(void *arg); 427 1.1 christos 428 1.1 christos static void 429 1.1 christos recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype, 430 1.1 christos const dns_name_t *qname, const dns_name_t *qdomain); 431 1.1 christos 432 1.1 christos static isc_result_t 433 1.1 christos query_resume(query_ctx_t *qctx); 434 1.1 christos 435 1.1 christos static isc_result_t 436 1.1 christos query_checkrrl(query_ctx_t *qctx, isc_result_t result); 437 1.1 christos 438 1.1 christos static isc_result_t 439 1.1 christos query_checkrpz(query_ctx_t *qctx, isc_result_t result); 440 1.1 christos 441 1.1 christos static isc_result_t 442 1.1 christos query_rpzcname(query_ctx_t *qctx, dns_name_t *cname); 443 1.1 christos 444 1.1 christos static isc_result_t 445 1.1 christos query_gotanswer(query_ctx_t *qctx, isc_result_t result); 446 1.1 christos 447 1.1 christos static void 448 1.1 christos query_addnoqnameproof(query_ctx_t *qctx); 449 1.1 christos 450 1.1 christos static isc_result_t 451 1.1 christos query_respond_any(query_ctx_t *qctx); 452 1.1 christos 453 1.1 christos static isc_result_t 454 1.1 christos query_respond(query_ctx_t *qctx); 455 1.1 christos 456 1.1 christos static isc_result_t 457 1.1 christos query_dns64(query_ctx_t *qctx); 458 1.1 christos 459 1.1 christos static void 460 1.1 christos query_filter64(query_ctx_t *qctx); 461 1.1 christos 462 1.1 christos static isc_result_t 463 1.1 christos query_notfound(query_ctx_t *qctx); 464 1.1 christos 465 1.1 christos static isc_result_t 466 1.1 christos query_zone_delegation(query_ctx_t *qctx); 467 1.1 christos 468 1.1 christos static isc_result_t 469 1.1 christos query_delegation(query_ctx_t *qctx); 470 1.1 christos 471 1.3 christos static isc_result_t 472 1.3 christos query_delegation_recurse(query_ctx_t *qctx); 473 1.3 christos 474 1.1 christos static void 475 1.1 christos query_addds(query_ctx_t *qctx); 476 1.1 christos 477 1.1 christos static isc_result_t 478 1.1 christos query_nodata(query_ctx_t *qctx, isc_result_t result); 479 1.1 christos 480 1.1 christos static isc_result_t 481 1.1 christos query_sign_nodata(query_ctx_t *qctx); 482 1.1 christos 483 1.1 christos static void 484 1.1 christos query_addnxrrsetnsec(query_ctx_t *qctx); 485 1.1 christos 486 1.1 christos static isc_result_t 487 1.18 christos query_nxdomain(query_ctx_t *qctx, isc_result_t result); 488 1.1 christos 489 1.1 christos static isc_result_t 490 1.18 christos query_redirect(query_ctx_t *qctx, isc_result_t result); 491 1.1 christos 492 1.1 christos static isc_result_t 493 1.1 christos query_ncache(query_ctx_t *qctx, isc_result_t result); 494 1.1 christos 495 1.1 christos static isc_result_t 496 1.1 christos query_coveringnsec(query_ctx_t *qctx); 497 1.1 christos 498 1.1 christos static isc_result_t 499 1.3 christos query_zerottl_refetch(query_ctx_t *qctx); 500 1.3 christos 501 1.3 christos static isc_result_t 502 1.1 christos query_cname(query_ctx_t *qctx); 503 1.1 christos 504 1.1 christos static isc_result_t 505 1.1 christos query_dname(query_ctx_t *qctx); 506 1.1 christos 507 1.23 christos static void 508 1.1 christos query_addcname(query_ctx_t *qctx, dns_trust_t trust, dns_ttl_t ttl); 509 1.1 christos 510 1.1 christos static isc_result_t 511 1.1 christos query_prepresponse(query_ctx_t *qctx); 512 1.1 christos 513 1.1 christos static isc_result_t 514 1.1 christos query_addsoa(query_ctx_t *qctx, unsigned int override_ttl, 515 1.1 christos dns_section_t section); 516 1.1 christos 517 1.1 christos static isc_result_t 518 1.1 christos query_addns(query_ctx_t *qctx); 519 1.1 christos 520 1.1 christos static void 521 1.1 christos query_addbestns(query_ctx_t *qctx); 522 1.1 christos 523 1.1 christos static void 524 1.3 christos query_addwildcardproof(query_ctx_t *qctx, bool ispositive, bool nodata); 525 1.1 christos 526 1.1 christos static void 527 1.1 christos query_addauth(query_ctx_t *qctx); 528 1.1 christos 529 1.3 christos /* 530 1.1 christos * Increment query statistics counters. 531 1.1 christos */ 532 1.15 christos static void 533 1.1 christos inc_stats(ns_client_t *client, isc_statscounter_t counter) { 534 1.1 christos dns_zone_t *zone = client->query.authzone; 535 1.1 christos dns_rdatatype_t qtype; 536 1.1 christos dns_rdataset_t *rdataset; 537 1.1 christos isc_stats_t *zonestats; 538 1.1 christos dns_stats_t *querystats = NULL; 539 1.1 christos 540 1.23 christos ns_stats_increment(client->manager->sctx->nsstats, counter); 541 1.1 christos 542 1.9 christos if (zone == NULL) { 543 1.1 christos return; 544 1.9 christos } 545 1.1 christos 546 1.1 christos /* Do regular response type stats */ 547 1.1 christos zonestats = dns_zone_getrequeststats(zone); 548 1.1 christos 549 1.9 christos if (zonestats != NULL) { 550 1.1 christos isc_stats_increment(zonestats, counter); 551 1.9 christos } 552 1.1 christos 553 1.1 christos /* Do query type statistics 554 1.1 christos * 555 1.1 christos * We only increment per-type if we're using the authoritative 556 1.1 christos * answer counter, preventing double-counting. 557 1.1 christos */ 558 1.1 christos if (counter == ns_statscounter_authans) { 559 1.1 christos querystats = dns_zone_getrcvquerystats(zone); 560 1.1 christos if (querystats != NULL) { 561 1.1 christos rdataset = ISC_LIST_HEAD(client->query.qname->list); 562 1.1 christos if (rdataset != NULL) { 563 1.1 christos qtype = rdataset->type; 564 1.1 christos dns_rdatatypestats_increment(querystats, qtype); 565 1.1 christos } 566 1.1 christos } 567 1.1 christos } 568 1.1 christos } 569 1.1 christos 570 1.23 christos #define NS_CLIENT_FLAGS_FORMATSIZE sizeof("+E(255)STDCV") 571 1.23 christos 572 1.23 christos static inline void 573 1.23 christos ns_client_log_flags(ns_client_t *client, unsigned int flags, 574 1.23 christos unsigned int extflags, char *buf, size_t len) { 575 1.23 christos isc_buffer_t b; 576 1.23 christos 577 1.23 christos isc_buffer_init(&b, buf, len); 578 1.23 christos isc_buffer_putuint8(&b, WANTRECURSION(client) ? '+' : '-'); 579 1.23 christos if (client->ednsversion >= 0) { 580 1.23 christos char ednsbuf[sizeof("E(255)")] = { 0 }; 581 1.23 christos 582 1.23 christos snprintf(ednsbuf, sizeof(ednsbuf), "E(%hhu)", 583 1.23 christos (unsigned char)client->ednsversion); 584 1.23 christos isc_buffer_putstr(&b, ednsbuf); 585 1.23 christos } 586 1.23 christos if (client->signer != NULL) { 587 1.23 christos isc_buffer_putuint8(&b, 'S'); 588 1.23 christos } 589 1.23 christos if (TCP(client)) { 590 1.23 christos isc_buffer_putuint8(&b, 'T'); 591 1.23 christos } 592 1.23 christos if ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) { 593 1.23 christos isc_buffer_putuint8(&b, 'D'); 594 1.23 christos } 595 1.23 christos if ((flags & DNS_MESSAGEFLAG_CD) != 0) { 596 1.23 christos isc_buffer_putuint8(&b, 'C'); 597 1.23 christos } 598 1.23 christos if (HAVECOOKIE(client)) { 599 1.23 christos isc_buffer_putuint8(&b, 'V'); 600 1.23 christos } else if (WANTCOOKIE(client)) { 601 1.23 christos isc_buffer_putuint8(&b, 'K'); 602 1.23 christos } 603 1.23 christos isc_buffer_putuint8(&b, 0); 604 1.23 christos } 605 1.23 christos 606 1.23 christos #define NS_CLIENT_ECS_FORMATSIZE (DNS_ECS_FORMATSIZE + sizeof(" [ECS ]") - 1) 607 1.23 christos 608 1.23 christos static inline void 609 1.23 christos ns_client_log_ecs(ns_client_t *client, char *ecsbuf, size_t len) { 610 1.23 christos strlcpy(ecsbuf, " [ECS ", len); 611 1.23 christos dns_ecs_format(&client->ecs, ecsbuf + 6, len - 6); 612 1.23 christos strlcat(ecsbuf, "]", len); 613 1.23 christos } 614 1.23 christos 615 1.23 christos static inline void 616 1.23 christos log_response(ns_client_t *client, dns_rcode_t rcode) { 617 1.23 christos char namebuf[DNS_NAME_FORMATSIZE]; 618 1.23 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 619 1.23 christos char classbuf[DNS_RDATACLASS_FORMATSIZE]; 620 1.23 christos char rcodebuf[20]; 621 1.23 christos char onbuf[ISC_NETADDR_FORMATSIZE]; 622 1.23 christos char ecsbuf[NS_CLIENT_ECS_FORMATSIZE] = { 0 }; 623 1.23 christos char flagsbuf[NS_CLIENT_FLAGS_FORMATSIZE] = { 0 }; 624 1.23 christos isc_buffer_t b; 625 1.23 christos int level = ISC_LOG_INFO; 626 1.23 christos 627 1.23 christos if (!isc_log_wouldlog(ns_lctx, level)) { 628 1.23 christos return; 629 1.23 christos } 630 1.23 christos 631 1.23 christos dns_name_format(client->query.origqname, namebuf, sizeof(namebuf)); 632 1.23 christos dns_rdataclass_format(client->message->rdclass, classbuf, 633 1.23 christos sizeof(classbuf)); 634 1.23 christos dns_rdatatype_format(client->query.qtype, typebuf, sizeof(typebuf)); 635 1.23 christos isc_buffer_init(&b, rcodebuf, sizeof(rcodebuf)); 636 1.23 christos dns_rcode_totext(rcode, &b); 637 1.23 christos isc_buffer_putuint8(&b, 0); 638 1.23 christos isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf)); 639 1.23 christos 640 1.23 christos if (HAVEECS(client)) { 641 1.23 christos ns_client_log_ecs(client, ecsbuf, sizeof(ecsbuf)); 642 1.23 christos } 643 1.23 christos 644 1.23 christos ns_client_log_flags(client, client->message->flags, client->extflags, 645 1.23 christos flagsbuf, sizeof(flagsbuf)); 646 1.23 christos ns_client_log(client, NS_LOGCATEGORY_RESPONSES, NS_LOGMODULE_QUERY, 647 1.23 christos level, "response: %s %s %s %s %u %u %u %s (%s)%s", 648 1.23 christos namebuf, classbuf, typebuf, rcodebuf, 649 1.23 christos client->message->counts[DNS_SECTION_ANSWER], 650 1.23 christos client->message->counts[DNS_SECTION_AUTHORITY], 651 1.23 christos client->message->counts[DNS_SECTION_ADDITIONAL], flagsbuf, 652 1.23 christos onbuf, ecsbuf); 653 1.23 christos } 654 1.23 christos 655 1.1 christos static void 656 1.1 christos query_send(ns_client_t *client) { 657 1.1 christos isc_statscounter_t counter; 658 1.1 christos 659 1.9 christos if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0) { 660 1.1 christos inc_stats(client, ns_statscounter_nonauthans); 661 1.9 christos } else { 662 1.1 christos inc_stats(client, ns_statscounter_authans); 663 1.9 christos } 664 1.1 christos 665 1.1 christos if (client->message->rcode == dns_rcode_noerror) { 666 1.1 christos dns_section_t answer = DNS_SECTION_ANSWER; 667 1.1 christos if (ISC_LIST_EMPTY(client->message->sections[answer])) { 668 1.9 christos if (client->query.isreferral) { 669 1.1 christos counter = ns_statscounter_referral; 670 1.9 christos } else { 671 1.1 christos counter = ns_statscounter_nxrrset; 672 1.9 christos } 673 1.9 christos } else { 674 1.1 christos counter = ns_statscounter_success; 675 1.9 christos } 676 1.9 christos } else if (client->message->rcode == dns_rcode_nxdomain) { 677 1.1 christos counter = ns_statscounter_nxdomain; 678 1.9 christos } else if (client->message->rcode == dns_rcode_badcookie) { 679 1.1 christos counter = ns_statscounter_badcookie; 680 1.9 christos } else { /* We end up here in case of YXDOMAIN, and maybe others */ 681 1.1 christos counter = ns_statscounter_failure; 682 1.9 christos } 683 1.1 christos 684 1.1 christos inc_stats(client, counter); 685 1.1 christos ns_client_send(client); 686 1.11 christos 687 1.23 christos if ((client->manager->sctx->options & NS_SERVER_LOGRESPONSES) != 0) { 688 1.23 christos log_response(client, client->message->rcode); 689 1.11 christos } 690 1.23 christos 691 1.23 christos isc_nmhandle_detach(&client->reqhandle); 692 1.1 christos } 693 1.1 christos 694 1.1 christos static void 695 1.1 christos query_error(ns_client_t *client, isc_result_t result, int line) { 696 1.1 christos int loglevel = ISC_LOG_DEBUG(3); 697 1.23 christos dns_rcode_t rcode; 698 1.1 christos 699 1.23 christos rcode = dns_result_torcode(result); 700 1.23 christos switch (rcode) { 701 1.3 christos case dns_rcode_servfail: 702 1.1 christos loglevel = ISC_LOG_DEBUG(1); 703 1.1 christos inc_stats(client, ns_statscounter_servfail); 704 1.1 christos break; 705 1.3 christos case dns_rcode_formerr: 706 1.1 christos inc_stats(client, ns_statscounter_formerr); 707 1.1 christos break; 708 1.1 christos default: 709 1.1 christos inc_stats(client, ns_statscounter_failure); 710 1.1 christos break; 711 1.1 christos } 712 1.1 christos 713 1.23 christos if ((client->manager->sctx->options & NS_SERVER_LOGQUERIES) != 0) { 714 1.1 christos loglevel = ISC_LOG_INFO; 715 1.9 christos } 716 1.1 christos 717 1.1 christos log_queryerror(client, result, line, loglevel); 718 1.1 christos 719 1.1 christos ns_client_error(client, result); 720 1.11 christos 721 1.23 christos if (client->query.origqname != NULL && 722 1.23 christos (client->manager->sctx->options & NS_SERVER_LOGRESPONSES) != 0) 723 1.23 christos { 724 1.23 christos log_response(client, rcode); 725 1.11 christos } 726 1.23 christos 727 1.23 christos isc_nmhandle_detach(&client->reqhandle); 728 1.1 christos } 729 1.1 christos 730 1.1 christos static void 731 1.1 christos query_next(ns_client_t *client, isc_result_t result) { 732 1.9 christos if (result == DNS_R_DUPLICATE) { 733 1.1 christos inc_stats(client, ns_statscounter_duplicate); 734 1.9 christos } else if (result == DNS_R_DROP) { 735 1.1 christos inc_stats(client, ns_statscounter_dropped); 736 1.9 christos } else { 737 1.1 christos inc_stats(client, ns_statscounter_failure); 738 1.9 christos } 739 1.9 christos ns_client_drop(client, result); 740 1.23 christos isc_nmhandle_detach(&client->reqhandle); 741 1.1 christos } 742 1.1 christos 743 1.15 christos static void 744 1.3 christos query_freefreeversions(ns_client_t *client, bool everything) { 745 1.1 christos ns_dbversion_t *dbversion, *dbversion_next; 746 1.1 christos unsigned int i; 747 1.1 christos 748 1.1 christos for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0; 749 1.9 christos dbversion != NULL; dbversion = dbversion_next, i++) 750 1.1 christos { 751 1.1 christos dbversion_next = ISC_LIST_NEXT(dbversion, link); 752 1.1 christos /* 753 1.1 christos * If we're not freeing everything, we keep the first three 754 1.1 christos * dbversions structures around. 755 1.1 christos */ 756 1.1 christos if (i > 3 || everything) { 757 1.1 christos ISC_LIST_UNLINK(client->query.freeversions, dbversion, 758 1.1 christos link); 759 1.23 christos isc_mem_put(client->manager->mctx, dbversion, 760 1.1 christos sizeof(*dbversion)); 761 1.1 christos } 762 1.1 christos } 763 1.1 christos } 764 1.1 christos 765 1.1 christos void 766 1.1 christos ns_query_cancel(ns_client_t *client) { 767 1.1 christos REQUIRE(NS_CLIENT_VALID(client)); 768 1.1 christos 769 1.1 christos LOCK(&client->query.fetchlock); 770 1.23 christos for (int i = 0; i < RECTYPE_COUNT; i++) { 771 1.23 christos dns_fetch_t **fetchp = &client->query.recursions[i].fetch; 772 1.23 christos if (*fetchp != NULL) { 773 1.23 christos dns_resolver_cancelfetch(*fetchp); 774 1.23 christos *fetchp = NULL; 775 1.23 christos } 776 1.1 christos } 777 1.20 christos if (client->query.hookactx != NULL) { 778 1.20 christos client->query.hookactx->cancel(client->query.hookactx); 779 1.20 christos client->query.hookactx = NULL; 780 1.20 christos } 781 1.1 christos UNLOCK(&client->query.fetchlock); 782 1.1 christos } 783 1.1 christos 784 1.15 christos static void 785 1.3 christos query_reset(ns_client_t *client, bool everything) { 786 1.1 christos isc_buffer_t *dbuf, *dbuf_next; 787 1.1 christos ns_dbversion_t *dbversion, *dbversion_next; 788 1.1 christos 789 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_reset"); 790 1.1 christos 791 1.1 christos /*% 792 1.1 christos * Reset the query state of a client to its default state. 793 1.1 christos */ 794 1.1 christos 795 1.1 christos /* 796 1.1 christos * Cancel the fetch if it's running. 797 1.1 christos */ 798 1.1 christos ns_query_cancel(client); 799 1.1 christos 800 1.1 christos /* 801 1.1 christos * Cleanup any active versions. 802 1.1 christos */ 803 1.1 christos for (dbversion = ISC_LIST_HEAD(client->query.activeversions); 804 1.9 christos dbversion != NULL; dbversion = dbversion_next) 805 1.9 christos { 806 1.1 christos dbversion_next = ISC_LIST_NEXT(dbversion, link); 807 1.9 christos dns_db_closeversion(dbversion->db, &dbversion->version, false); 808 1.1 christos dns_db_detach(&dbversion->db); 809 1.9 christos ISC_LIST_INITANDAPPEND(client->query.freeversions, dbversion, 810 1.9 christos link); 811 1.1 christos } 812 1.1 christos ISC_LIST_INIT(client->query.activeversions); 813 1.1 christos 814 1.9 christos if (client->query.authdb != NULL) { 815 1.1 christos dns_db_detach(&client->query.authdb); 816 1.9 christos } 817 1.9 christos if (client->query.authzone != NULL) { 818 1.1 christos dns_zone_detach(&client->query.authzone); 819 1.9 christos } 820 1.1 christos 821 1.9 christos if (client->query.dns64_aaaa != NULL) { 822 1.3 christos ns_client_putrdataset(client, &client->query.dns64_aaaa); 823 1.9 christos } 824 1.9 christos if (client->query.dns64_sigaaaa != NULL) { 825 1.3 christos ns_client_putrdataset(client, &client->query.dns64_sigaaaa); 826 1.9 christos } 827 1.1 christos if (client->query.dns64_aaaaok != NULL) { 828 1.23 christos isc_mem_cput(client->manager->mctx, client->query.dns64_aaaaok, 829 1.23 christos client->query.dns64_aaaaoklen, sizeof(bool)); 830 1.9 christos client->query.dns64_aaaaok = NULL; 831 1.9 christos client->query.dns64_aaaaoklen = 0; 832 1.1 christos } 833 1.1 christos 834 1.3 christos ns_client_putrdataset(client, &client->query.redirect.rdataset); 835 1.3 christos ns_client_putrdataset(client, &client->query.redirect.sigrdataset); 836 1.1 christos if (client->query.redirect.db != NULL) { 837 1.9 christos if (client->query.redirect.node != NULL) { 838 1.1 christos dns_db_detachnode(client->query.redirect.db, 839 1.1 christos &client->query.redirect.node); 840 1.9 christos } 841 1.1 christos dns_db_detach(&client->query.redirect.db); 842 1.1 christos } 843 1.9 christos if (client->query.redirect.zone != NULL) { 844 1.1 christos dns_zone_detach(&client->query.redirect.zone); 845 1.9 christos } 846 1.1 christos 847 1.1 christos query_freefreeversions(client, everything); 848 1.1 christos 849 1.9 christos for (dbuf = ISC_LIST_HEAD(client->query.namebufs); dbuf != NULL; 850 1.9 christos dbuf = dbuf_next) 851 1.9 christos { 852 1.1 christos dbuf_next = ISC_LIST_NEXT(dbuf, link); 853 1.1 christos if (dbuf_next != NULL || everything) { 854 1.1 christos ISC_LIST_UNLINK(client->query.namebufs, dbuf, link); 855 1.1 christos isc_buffer_free(&dbuf); 856 1.1 christos } 857 1.1 christos } 858 1.1 christos 859 1.1 christos if (client->query.restarts > 0) { 860 1.1 christos /* 861 1.1 christos * client->query.qname was dynamically allocated. 862 1.1 christos */ 863 1.9 christos dns_message_puttempname(client->message, &client->query.qname); 864 1.1 christos } 865 1.1 christos client->query.qname = NULL; 866 1.1 christos client->query.attributes = (NS_QUERYATTR_RECURSIONOK | 867 1.9 christos NS_QUERYATTR_CACHEOK | NS_QUERYATTR_SECURE); 868 1.1 christos client->query.restarts = 0; 869 1.3 christos client->query.timerset = false; 870 1.1 christos if (client->query.rpz_st != NULL) { 871 1.1 christos rpz_st_clear(client); 872 1.1 christos if (everything) { 873 1.1 christos INSIST(client->query.rpz_st->rpsdb == NULL); 874 1.23 christos isc_mem_put(client->manager->mctx, client->query.rpz_st, 875 1.1 christos sizeof(*client->query.rpz_st)); 876 1.1 christos client->query.rpz_st = NULL; 877 1.1 christos } 878 1.1 christos } 879 1.24 christos if (client->query.qc != NULL) { 880 1.24 christos isc_counter_detach(&client->query.qc); 881 1.24 christos } 882 1.1 christos client->query.origqname = NULL; 883 1.1 christos client->query.dboptions = 0; 884 1.1 christos client->query.fetchoptions = 0; 885 1.1 christos client->query.gluedb = NULL; 886 1.3 christos client->query.authdbset = false; 887 1.3 christos client->query.isreferral = false; 888 1.1 christos client->query.dns64_options = 0; 889 1.3 christos client->query.dns64_ttl = UINT32_MAX; 890 1.3 christos recparam_update(&client->query.recparam, 0, NULL, NULL); 891 1.1 christos client->query.root_key_sentinel_keyid = 0; 892 1.3 christos client->query.root_key_sentinel_is_ta = false; 893 1.3 christos client->query.root_key_sentinel_not_ta = false; 894 1.1 christos } 895 1.1 christos 896 1.1 christos static void 897 1.9 christos query_cleanup(ns_client_t *client) { 898 1.3 christos query_reset(client, false); 899 1.1 christos } 900 1.1 christos 901 1.1 christos void 902 1.1 christos ns_query_free(ns_client_t *client) { 903 1.1 christos REQUIRE(NS_CLIENT_VALID(client)); 904 1.1 christos 905 1.3 christos query_reset(client, true); 906 1.1 christos } 907 1.1 christos 908 1.23 christos void 909 1.1 christos ns_query_init(ns_client_t *client) { 910 1.23 christos REQUIRE(NS_CLIENT_VALID(client)); 911 1.1 christos 912 1.23 christos client->query = (ns_query_t){ 0 }; 913 1.1 christos 914 1.1 christos ISC_LIST_INIT(client->query.namebufs); 915 1.1 christos ISC_LIST_INIT(client->query.activeversions); 916 1.1 christos ISC_LIST_INIT(client->query.freeversions); 917 1.24 christos 918 1.1 christos /* 919 1.1 christos * This mutex is destroyed when the client is destroyed in 920 1.1 christos * exit_check(). 921 1.1 christos */ 922 1.3 christos isc_mutex_init(&client->query.fetchlock); 923 1.1 christos client->query.redirect.fname = 924 1.1 christos dns_fixedname_initname(&client->query.redirect.fixed); 925 1.3 christos query_reset(client, false); 926 1.14 christos ns_client_newdbversion(client, 3); 927 1.14 christos ns_client_newnamebuf(client); 928 1.1 christos } 929 1.1 christos 930 1.3 christos /*% 931 1.3 christos * Check if 'client' is allowed to query the cache of its associated view. 932 1.23 christos * Unless 'options' has the 'nolog' flag set, log the result of cache ACL 933 1.3 christos * evaluation using the appropriate level, along with 'name' and 'qtype'. 934 1.3 christos * 935 1.3 christos * The cache ACL is only evaluated once for each client and then the result is 936 1.3 christos * cached: if NS_QUERYATTR_CACHEACLOKVALID is set in client->query.attributes, 937 1.3 christos * cache ACL evaluation has already been performed. The evaluation result is 938 1.3 christos * also stored in client->query.attributes: if NS_QUERYATTR_CACHEACLOK is set, 939 1.3 christos * the client is allowed cache access. 940 1.3 christos * 941 1.3 christos * Returns: 942 1.3 christos * 943 1.3 christos *\li #ISC_R_SUCCESS 'client' is allowed to access cache 944 1.3 christos *\li #DNS_R_REFUSED 'client' is not allowed to access cache 945 1.3 christos */ 946 1.3 christos static isc_result_t 947 1.3 christos query_checkcacheaccess(ns_client_t *client, const dns_name_t *name, 948 1.23 christos dns_rdatatype_t qtype, dns_getdb_options_t options) { 949 1.3 christos isc_result_t result; 950 1.3 christos 951 1.3 christos if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) == 0) { 952 1.20 christos enum refusal_reasons { 953 1.20 christos ALLOW_QUERY_CACHE, 954 1.20 christos ALLOW_QUERY_CACHE_ON 955 1.20 christos }; 956 1.20 christos static const char *acl_desc[] = { 957 1.20 christos "allow-query-cache did not match", 958 1.20 christos "allow-query-cache-on did not match", 959 1.20 christos }; 960 1.20 christos 961 1.3 christos /* 962 1.3 christos * The view's cache ACLs have not yet been evaluated. 963 1.3 christos * Do it now. Both allow-query-cache and 964 1.20 christos * allow-query-cache-on must be satisfied. 965 1.3 christos */ 966 1.3 christos char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")]; 967 1.1 christos 968 1.20 christos enum refusal_reasons refusal_reason = ALLOW_QUERY_CACHE; 969 1.3 christos result = ns_client_checkaclsilent(client, NULL, 970 1.9 christos client->view->cacheacl, true); 971 1.3 christos if (result == ISC_R_SUCCESS) { 972 1.20 christos refusal_reason = ALLOW_QUERY_CACHE_ON; 973 1.9 christos result = ns_client_checkaclsilent( 974 1.9 christos client, &client->destaddr, 975 1.9 christos client->view->cacheonacl, true); 976 1.9 christos } 977 1.3 christos if (result == ISC_R_SUCCESS) { 978 1.3 christos /* 979 1.3 christos * We were allowed by the "allow-query-cache" ACL. 980 1.3 christos */ 981 1.3 christos client->query.attributes |= NS_QUERYATTR_CACHEACLOK; 982 1.23 christos if (!options.nolog && 983 1.23 christos isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(3))) 984 1.3 christos { 985 1.3 christos ns_client_aclmsg("query (cache)", name, qtype, 986 1.3 christos client->view->rdclass, msg, 987 1.3 christos sizeof(msg)); 988 1.3 christos ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 989 1.3 christos NS_LOGMODULE_QUERY, 990 1.3 christos ISC_LOG_DEBUG(3), "%s approved", 991 1.3 christos msg); 992 1.3 christos } 993 1.20 christos } else { 994 1.3 christos /* 995 1.3 christos * We were denied by the "allow-query-cache" ACL. 996 1.3 christos * There is no need to clear NS_QUERYATTR_CACHEACLOK 997 1.3 christos * since it is cleared by query_reset(), before query 998 1.3 christos * processing starts. 999 1.3 christos */ 1000 1.24 christos dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL); 1001 1.20 christos 1002 1.23 christos if (!options.nolog) { 1003 1.20 christos ns_client_aclmsg("query (cache)", name, qtype, 1004 1.20 christos client->view->rdclass, msg, 1005 1.20 christos sizeof(msg)); 1006 1.20 christos ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 1007 1.20 christos NS_LOGMODULE_QUERY, ISC_LOG_INFO, 1008 1.20 christos "%s denied (%s)", msg, 1009 1.20 christos acl_desc[refusal_reason]); 1010 1.20 christos } 1011 1.3 christos } 1012 1.1 christos 1013 1.1 christos /* 1014 1.3 christos * Evaluation has been finished; make sure we will just consult 1015 1.3 christos * NS_QUERYATTR_CACHEACLOK for this client from now on. 1016 1.1 christos */ 1017 1.3 christos client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID; 1018 1.1 christos } 1019 1.1 christos 1020 1.23 christos return (client->query.attributes & NS_QUERYATTR_CACHEACLOK) != 0 1021 1.23 christos ? ISC_R_SUCCESS 1022 1.23 christos : DNS_R_REFUSED; 1023 1.1 christos } 1024 1.1 christos 1025 1.15 christos static isc_result_t 1026 1.1 christos query_validatezonedb(ns_client_t *client, const dns_name_t *name, 1027 1.23 christos dns_rdatatype_t qtype, dns_getdb_options_t options, 1028 1.1 christos dns_zone_t *zone, dns_db_t *db, 1029 1.9 christos dns_dbversion_t **versionp) { 1030 1.1 christos isc_result_t result; 1031 1.1 christos dns_acl_t *queryacl, *queryonacl; 1032 1.1 christos ns_dbversion_t *dbversion; 1033 1.1 christos 1034 1.1 christos REQUIRE(zone != NULL); 1035 1.1 christos REQUIRE(db != NULL); 1036 1.1 christos 1037 1.1 christos /* 1038 1.3 christos * Mirror zone data is treated as cache data. 1039 1.3 christos */ 1040 1.3 christos if (dns_zone_gettype(zone) == dns_zone_mirror) { 1041 1.23 christos return query_checkcacheaccess(client, name, qtype, options); 1042 1.3 christos } 1043 1.3 christos 1044 1.3 christos /* 1045 1.1 christos * This limits our searching to the zone where the first name 1046 1.1 christos * (the query target) was looked for. This prevents following 1047 1.1 christos * CNAMES or DNAMES into other zones and prevents returning 1048 1.1 christos * additional data from other zones. This does not apply if we're 1049 1.1 christos * answering a query where recursion is requested and allowed. 1050 1.1 christos */ 1051 1.1 christos if (client->query.rpz_st == NULL && 1052 1.1 christos !(WANTRECURSION(client) && RECURSIONOK(client)) && 1053 1.1 christos client->query.authdbset && db != client->query.authdb) 1054 1.1 christos { 1055 1.23 christos return DNS_R_REFUSED; 1056 1.1 christos } 1057 1.1 christos 1058 1.1 christos /* 1059 1.1 christos * Non recursive query to a static-stub zone is prohibited; its 1060 1.1 christos * zone content is not public data, but a part of local configuration 1061 1.1 christos * and should not be disclosed. 1062 1.1 christos */ 1063 1.1 christos if (dns_zone_gettype(zone) == dns_zone_staticstub && 1064 1.16 christos !RECURSIONOK(client)) 1065 1.16 christos { 1066 1.23 christos return DNS_R_REFUSED; 1067 1.1 christos } 1068 1.1 christos 1069 1.1 christos /* 1070 1.1 christos * If the zone has an ACL, we'll check it, otherwise 1071 1.1 christos * we use the view's "allow-query" ACL. Each ACL is only checked 1072 1.1 christos * once per query. 1073 1.1 christos * 1074 1.1 christos * Also, get the database version to use. 1075 1.1 christos */ 1076 1.1 christos 1077 1.1 christos /* 1078 1.1 christos * Get the current version of this database. 1079 1.1 christos */ 1080 1.3 christos dbversion = ns_client_findversion(client, db); 1081 1.1 christos if (dbversion == NULL) { 1082 1.1 christos CTRACE(ISC_LOG_ERROR, "unable to get db version"); 1083 1.23 christos return DNS_R_SERVFAIL; 1084 1.1 christos } 1085 1.1 christos 1086 1.23 christos if (options.ignoreacl) { 1087 1.1 christos goto approved; 1088 1.9 christos } 1089 1.1 christos if (dbversion->acl_checked) { 1090 1.9 christos if (!dbversion->queryok) { 1091 1.23 christos return DNS_R_REFUSED; 1092 1.9 christos } 1093 1.1 christos goto approved; 1094 1.1 christos } 1095 1.1 christos 1096 1.1 christos queryacl = dns_zone_getqueryacl(zone); 1097 1.1 christos if (queryacl == NULL) { 1098 1.1 christos queryacl = client->view->queryacl; 1099 1.9 christos if ((client->query.attributes & NS_QUERYATTR_QUERYOKVALID) != 0) 1100 1.9 christos { 1101 1.1 christos /* 1102 1.1 christos * We've evaluated the view's queryacl already. If 1103 1.1 christos * NS_QUERYATTR_QUERYOK is set, then the client is 1104 1.1 christos * allowed to make queries, otherwise the query should 1105 1.1 christos * be refused. 1106 1.1 christos */ 1107 1.3 christos dbversion->acl_checked = true; 1108 1.9 christos if ((client->query.attributes & NS_QUERYATTR_QUERYOK) == 1109 1.16 christos 0) 1110 1.16 christos { 1111 1.3 christos dbversion->queryok = false; 1112 1.23 christos return DNS_R_REFUSED; 1113 1.1 christos } 1114 1.3 christos dbversion->queryok = true; 1115 1.1 christos goto approved; 1116 1.1 christos } 1117 1.1 christos } 1118 1.1 christos 1119 1.3 christos result = ns_client_checkaclsilent(client, NULL, queryacl, true); 1120 1.23 christos if (!options.nolog) { 1121 1.1 christos char msg[NS_CLIENT_ACLMSGSIZE("query")]; 1122 1.1 christos if (result == ISC_R_SUCCESS) { 1123 1.1 christos if (isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(3))) { 1124 1.1 christos ns_client_aclmsg("query", name, qtype, 1125 1.9 christos client->view->rdclass, msg, 1126 1.9 christos sizeof(msg)); 1127 1.9 christos ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 1128 1.1 christos NS_LOGMODULE_QUERY, 1129 1.9 christos ISC_LOG_DEBUG(3), "%s approved", 1130 1.9 christos msg); 1131 1.1 christos } 1132 1.1 christos } else { 1133 1.1 christos ns_client_aclmsg("query", name, qtype, 1134 1.9 christos client->view->rdclass, msg, 1135 1.9 christos sizeof(msg)); 1136 1.1 christos ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 1137 1.1 christos NS_LOGMODULE_QUERY, ISC_LOG_INFO, 1138 1.1 christos "%s denied", msg); 1139 1.24 christos dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL); 1140 1.1 christos } 1141 1.1 christos } 1142 1.1 christos 1143 1.1 christos if (queryacl == client->view->queryacl) { 1144 1.1 christos if (result == ISC_R_SUCCESS) { 1145 1.1 christos /* 1146 1.1 christos * We were allowed by the default 1147 1.1 christos * "allow-query" ACL. Remember this so we 1148 1.1 christos * don't have to check again. 1149 1.1 christos */ 1150 1.1 christos client->query.attributes |= NS_QUERYATTR_QUERYOK; 1151 1.1 christos } 1152 1.1 christos /* 1153 1.1 christos * We've now evaluated the view's query ACL, and 1154 1.1 christos * the NS_QUERYATTR_QUERYOK attribute is now valid. 1155 1.1 christos */ 1156 1.1 christos client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; 1157 1.1 christos } 1158 1.1 christos 1159 1.1 christos /* If and only if we've gotten this far, check allow-query-on too */ 1160 1.1 christos if (result == ISC_R_SUCCESS) { 1161 1.1 christos queryonacl = dns_zone_getqueryonacl(zone); 1162 1.9 christos if (queryonacl == NULL) { 1163 1.1 christos queryonacl = client->view->queryonacl; 1164 1.9 christos } 1165 1.1 christos 1166 1.1 christos result = ns_client_checkaclsilent(client, &client->destaddr, 1167 1.3 christos queryonacl, true); 1168 1.20 christos if (result != ISC_R_SUCCESS) { 1169 1.24 christos dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL); 1170 1.20 christos } 1171 1.23 christos if (!options.nolog && result != ISC_R_SUCCESS) { 1172 1.1 christos ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 1173 1.1 christos NS_LOGMODULE_QUERY, ISC_LOG_INFO, 1174 1.1 christos "query-on denied"); 1175 1.9 christos } 1176 1.1 christos } 1177 1.1 christos 1178 1.3 christos dbversion->acl_checked = true; 1179 1.1 christos if (result != ISC_R_SUCCESS) { 1180 1.3 christos dbversion->queryok = false; 1181 1.23 christos return DNS_R_REFUSED; 1182 1.1 christos } 1183 1.3 christos dbversion->queryok = true; 1184 1.1 christos 1185 1.9 christos approved: 1186 1.1 christos /* Transfer ownership, if necessary. */ 1187 1.23 christos SET_IF_NOT_NULL(versionp, dbversion->version); 1188 1.23 christos return ISC_R_SUCCESS; 1189 1.1 christos } 1190 1.1 christos 1191 1.15 christos static isc_result_t 1192 1.1 christos query_getzonedb(ns_client_t *client, const dns_name_t *name, 1193 1.23 christos dns_rdatatype_t qtype, dns_getdb_options_t options, 1194 1.23 christos dns_zone_t **zonep, dns_db_t **dbp, 1195 1.23 christos dns_dbversion_t **versionp) { 1196 1.1 christos isc_result_t result; 1197 1.1 christos unsigned int ztoptions; 1198 1.1 christos dns_zone_t *zone = NULL; 1199 1.1 christos dns_db_t *db = NULL; 1200 1.3 christos bool partial = false; 1201 1.1 christos 1202 1.1 christos REQUIRE(zonep != NULL && *zonep == NULL); 1203 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL); 1204 1.1 christos 1205 1.1 christos /*% 1206 1.1 christos * Find a zone database to answer the query. 1207 1.1 christos */ 1208 1.3 christos ztoptions = DNS_ZTFIND_MIRROR; 1209 1.23 christos if (options.noexact) { 1210 1.3 christos ztoptions |= DNS_ZTFIND_NOEXACT; 1211 1.3 christos } 1212 1.1 christos 1213 1.23 christos result = dns_view_findzone(client->view, name, ztoptions, &zone); 1214 1.1 christos 1215 1.9 christos if (result == DNS_R_PARTIALMATCH) { 1216 1.3 christos partial = true; 1217 1.9 christos } 1218 1.9 christos if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { 1219 1.1 christos result = dns_zone_getdb(zone, &db); 1220 1.9 christos } 1221 1.1 christos 1222 1.9 christos if (result != ISC_R_SUCCESS) { 1223 1.1 christos goto fail; 1224 1.9 christos } 1225 1.1 christos 1226 1.1 christos result = query_validatezonedb(client, name, qtype, options, zone, db, 1227 1.1 christos versionp); 1228 1.1 christos 1229 1.9 christos if (result != ISC_R_SUCCESS) { 1230 1.1 christos goto fail; 1231 1.9 christos } 1232 1.1 christos 1233 1.1 christos /* Transfer ownership. */ 1234 1.1 christos *zonep = zone; 1235 1.1 christos *dbp = db; 1236 1.1 christos 1237 1.23 christos if (partial && options.partial) { 1238 1.23 christos return DNS_R_PARTIALMATCH; 1239 1.9 christos } 1240 1.23 christos return ISC_R_SUCCESS; 1241 1.1 christos 1242 1.9 christos fail: 1243 1.9 christos if (zone != NULL) { 1244 1.1 christos dns_zone_detach(&zone); 1245 1.9 christos } 1246 1.9 christos if (db != NULL) { 1247 1.1 christos dns_db_detach(&db); 1248 1.9 christos } 1249 1.1 christos 1250 1.23 christos return result; 1251 1.1 christos } 1252 1.1 christos 1253 1.1 christos static void 1254 1.9 christos rpz_log_rewrite(ns_client_t *client, bool disabled, dns_rpz_policy_t policy, 1255 1.9 christos dns_rpz_type_t type, dns_zone_t *p_zone, dns_name_t *p_name, 1256 1.9 christos dns_name_t *cname, dns_rpz_num_t rpz_num) { 1257 1.3 christos char cname_buf[DNS_NAME_FORMATSIZE] = { 0 }; 1258 1.3 christos char p_name_buf[DNS_NAME_FORMATSIZE]; 1259 1.1 christos char qname_buf[DNS_NAME_FORMATSIZE]; 1260 1.3 christos char classbuf[DNS_RDATACLASS_FORMATSIZE]; 1261 1.3 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 1262 1.1 christos const char *s1 = cname_buf, *s2 = cname_buf; 1263 1.3 christos dns_rdataset_t *rdataset; 1264 1.1 christos dns_rpz_st_t *st; 1265 1.3 christos isc_stats_t *zonestats; 1266 1.1 christos 1267 1.1 christos /* 1268 1.1 christos * Count enabled rewrites in the global counter. 1269 1.1 christos * Count both enabled and disabled rewrites for each zone. 1270 1.1 christos */ 1271 1.1 christos if (!disabled && policy != DNS_RPZ_POLICY_PASSTHRU) { 1272 1.23 christos ns_stats_increment(client->manager->sctx->nsstats, 1273 1.1 christos ns_statscounter_rpz_rewrites); 1274 1.1 christos } 1275 1.1 christos if (p_zone != NULL) { 1276 1.1 christos zonestats = dns_zone_getrequeststats(p_zone); 1277 1.9 christos if (zonestats != NULL) { 1278 1.1 christos isc_stats_increment(zonestats, 1279 1.1 christos ns_statscounter_rpz_rewrites); 1280 1.9 christos } 1281 1.1 christos } 1282 1.1 christos 1283 1.9 christos if (!isc_log_wouldlog(ns_lctx, DNS_RPZ_INFO_LEVEL)) { 1284 1.1 christos return; 1285 1.9 christos } 1286 1.1 christos 1287 1.1 christos st = client->query.rpz_st; 1288 1.9 christos if ((st->popt.no_log & DNS_RPZ_ZBIT(rpz_num)) != 0) { 1289 1.1 christos return; 1290 1.9 christos } 1291 1.1 christos 1292 1.1 christos dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf)); 1293 1.1 christos dns_name_format(p_name, p_name_buf, sizeof(p_name_buf)); 1294 1.1 christos if (cname != NULL) { 1295 1.1 christos s1 = " (CNAME to: "; 1296 1.1 christos dns_name_format(cname, cname_buf, sizeof(cname_buf)); 1297 1.1 christos s2 = ")"; 1298 1.1 christos } 1299 1.1 christos 1300 1.3 christos /* 1301 1.3 christos * Log Qclass and Qtype in addition to existing 1302 1.3 christos * fields. 1303 1.3 christos */ 1304 1.3 christos rdataset = ISC_LIST_HEAD(client->query.origqname->list); 1305 1.3 christos INSIST(rdataset != NULL); 1306 1.3 christos dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf)); 1307 1.3 christos dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); 1308 1.3 christos 1309 1.20 christos /* It's possible to have a separate log channel for rpz passthru. */ 1310 1.20 christos isc_logcategory_t *log_cat = (policy == DNS_RPZ_POLICY_PASSTHRU) 1311 1.20 christos ? DNS_LOGCATEGORY_RPZ_PASSTHRU 1312 1.20 christos : DNS_LOGCATEGORY_RPZ; 1313 1.20 christos 1314 1.20 christos ns_client_log(client, log_cat, NS_LOGMODULE_QUERY, DNS_RPZ_INFO_LEVEL, 1315 1.3 christos "%srpz %s %s rewrite %s/%s/%s via %s%s%s%s", 1316 1.9 christos disabled ? "disabled " : "", dns_rpz_type2str(type), 1317 1.9 christos dns_rpz_policy2str(policy), qname_buf, typebuf, classbuf, 1318 1.3 christos p_name_buf, s1, cname_buf, s2); 1319 1.1 christos } 1320 1.1 christos 1321 1.1 christos static void 1322 1.1 christos rpz_log_fail_helper(ns_client_t *client, int level, dns_name_t *p_name, 1323 1.1 christos dns_rpz_type_t rpz_type1, dns_rpz_type_t rpz_type2, 1324 1.9 christos const char *str, isc_result_t result) { 1325 1.1 christos char qnamebuf[DNS_NAME_FORMATSIZE]; 1326 1.1 christos char p_namebuf[DNS_NAME_FORMATSIZE]; 1327 1.1 christos const char *failed, *via, *slash, *str_blank; 1328 1.1 christos const char *rpztypestr1; 1329 1.1 christos const char *rpztypestr2; 1330 1.1 christos 1331 1.9 christos if (!isc_log_wouldlog(ns_lctx, level)) { 1332 1.1 christos return; 1333 1.9 christos } 1334 1.1 christos 1335 1.1 christos /* 1336 1.1 christos * bin/tests/system/rpz/tests.sh looks for "rpz.*failed" for problems. 1337 1.1 christos */ 1338 1.9 christos if (level <= DNS_RPZ_DEBUG_LEVEL1) { 1339 1.3 christos failed = " failed: "; 1340 1.9 christos } else { 1341 1.1 christos failed = ": "; 1342 1.9 christos } 1343 1.1 christos 1344 1.1 christos rpztypestr1 = dns_rpz_type2str(rpz_type1); 1345 1.1 christos if (rpz_type2 != DNS_RPZ_TYPE_BAD) { 1346 1.1 christos slash = "/"; 1347 1.1 christos rpztypestr2 = dns_rpz_type2str(rpz_type2); 1348 1.1 christos } else { 1349 1.1 christos slash = ""; 1350 1.1 christos rpztypestr2 = ""; 1351 1.1 christos } 1352 1.1 christos 1353 1.1 christos str_blank = (*str != ' ' && *str != '\0') ? " " : ""; 1354 1.1 christos 1355 1.1 christos dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf)); 1356 1.1 christos 1357 1.1 christos if (p_name != NULL) { 1358 1.1 christos via = " via "; 1359 1.1 christos dns_name_format(p_name, p_namebuf, sizeof(p_namebuf)); 1360 1.1 christos } else { 1361 1.1 christos via = ""; 1362 1.1 christos p_namebuf[0] = '\0'; 1363 1.1 christos } 1364 1.1 christos 1365 1.9 christos ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY, 1366 1.9 christos level, "rpz %s%s%s rewrite %s%s%s%s%s%s%s", rpztypestr1, 1367 1.9 christos slash, rpztypestr2, qnamebuf, via, p_namebuf, str_blank, 1368 1.1 christos str, failed, isc_result_totext(result)); 1369 1.1 christos } 1370 1.1 christos 1371 1.1 christos static void 1372 1.1 christos rpz_log_fail(ns_client_t *client, int level, dns_name_t *p_name, 1373 1.9 christos dns_rpz_type_t rpz_type, const char *str, isc_result_t result) { 1374 1.9 christos rpz_log_fail_helper(client, level, p_name, rpz_type, DNS_RPZ_TYPE_BAD, 1375 1.9 christos str, result); 1376 1.1 christos } 1377 1.1 christos 1378 1.1 christos /* 1379 1.1 christos * Get a policy rewrite zone database. 1380 1.1 christos */ 1381 1.1 christos static isc_result_t 1382 1.1 christos rpz_getdb(ns_client_t *client, dns_name_t *p_name, dns_rpz_type_t rpz_type, 1383 1.9 christos dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp) { 1384 1.1 christos char qnamebuf[DNS_NAME_FORMATSIZE]; 1385 1.1 christos char p_namebuf[DNS_NAME_FORMATSIZE]; 1386 1.1 christos dns_dbversion_t *rpz_version = NULL; 1387 1.1 christos isc_result_t result; 1388 1.1 christos 1389 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_getdb"); 1390 1.1 christos 1391 1.23 christos dns_getdb_options_t options = { .ignoreacl = true }; 1392 1.23 christos result = query_getzonedb(client, p_name, dns_rdatatype_any, options, 1393 1.23 christos zonep, dbp, &rpz_version); 1394 1.1 christos if (result == ISC_R_SUCCESS) { 1395 1.1 christos dns_rpz_st_t *st = client->query.rpz_st; 1396 1.1 christos 1397 1.1 christos /* 1398 1.1 christos * It isn't meaningful to log this message when 1399 1.1 christos * logging is disabled for some policy zones. 1400 1.1 christos */ 1401 1.1 christos if (st->popt.no_log == 0 && 1402 1.16 christos isc_log_wouldlog(ns_lctx, DNS_RPZ_DEBUG_LEVEL2)) 1403 1.16 christos { 1404 1.1 christos dns_name_format(client->query.qname, qnamebuf, 1405 1.1 christos sizeof(qnamebuf)); 1406 1.1 christos dns_name_format(p_name, p_namebuf, sizeof(p_namebuf)); 1407 1.1 christos ns_client_log(client, DNS_LOGCATEGORY_RPZ, 1408 1.1 christos NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2, 1409 1.1 christos "try rpz %s rewrite %s via %s", 1410 1.9 christos dns_rpz_type2str(rpz_type), qnamebuf, 1411 1.9 christos p_namebuf); 1412 1.1 christos } 1413 1.1 christos *versionp = rpz_version; 1414 1.23 christos return ISC_R_SUCCESS; 1415 1.1 christos } 1416 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, 1417 1.3 christos "query_getzonedb()", result); 1418 1.23 christos return result; 1419 1.1 christos } 1420 1.1 christos 1421 1.3 christos /*% 1422 1.3 christos * Find a cache database to answer the query. This may fail with DNS_R_REFUSED 1423 1.3 christos * if the client is not allowed to use the cache. 1424 1.3 christos */ 1425 1.15 christos static isc_result_t 1426 1.1 christos query_getcachedb(ns_client_t *client, const dns_name_t *name, 1427 1.23 christos dns_rdatatype_t qtype, dns_db_t **dbp, 1428 1.23 christos dns_getdb_options_t options) { 1429 1.1 christos isc_result_t result; 1430 1.1 christos dns_db_t *db = NULL; 1431 1.1 christos 1432 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL); 1433 1.1 christos 1434 1.3 christos if (!USECACHE(client)) { 1435 1.23 christos return DNS_R_REFUSED; 1436 1.1 christos } 1437 1.1 christos 1438 1.3 christos dns_db_attach(client->view->cachedb, &db); 1439 1.1 christos 1440 1.3 christos result = query_checkcacheaccess(client, name, qtype, options); 1441 1.3 christos if (result != ISC_R_SUCCESS) { 1442 1.3 christos dns_db_detach(&db); 1443 1.1 christos } 1444 1.1 christos 1445 1.3 christos /* 1446 1.3 christos * If query_checkcacheaccess() succeeded, transfer ownership of 'db'. 1447 1.3 christos * Otherwise, 'db' will be NULL due to the dns_db_detach() call above. 1448 1.3 christos */ 1449 1.1 christos *dbp = db; 1450 1.1 christos 1451 1.23 christos return result; 1452 1.3 christos } 1453 1.1 christos 1454 1.15 christos static isc_result_t 1455 1.3 christos query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, 1456 1.23 christos dns_getdb_options_t options, dns_zone_t **zonep, dns_db_t **dbp, 1457 1.9 christos dns_dbversion_t **versionp, bool *is_zonep) { 1458 1.1 christos isc_result_t result; 1459 1.1 christos isc_result_t tresult; 1460 1.1 christos unsigned int namelabels; 1461 1.1 christos unsigned int zonelabels; 1462 1.1 christos dns_zone_t *zone = NULL; 1463 1.1 christos 1464 1.1 christos REQUIRE(zonep != NULL && *zonep == NULL); 1465 1.1 christos 1466 1.1 christos /* Calculate how many labels are in name. */ 1467 1.1 christos namelabels = dns_name_countlabels(name); 1468 1.1 christos zonelabels = 0; 1469 1.1 christos 1470 1.1 christos /* Try to find name in bind's standard database. */ 1471 1.9 christos result = query_getzonedb(client, name, qtype, options, &zone, dbp, 1472 1.9 christos versionp); 1473 1.1 christos 1474 1.1 christos /* See how many labels are in the zone's name. */ 1475 1.5 christos if (result == ISC_R_SUCCESS && zone != NULL) { 1476 1.1 christos zonelabels = dns_name_countlabels(dns_zone_getorigin(zone)); 1477 1.5 christos } 1478 1.1 christos 1479 1.1 christos /* 1480 1.1 christos * If # zone labels < # name labels, try to find an even better match 1481 1.1 christos * Only try if DLZ drivers are loaded for this view 1482 1.1 christos */ 1483 1.20 christos if (zonelabels < namelabels && 1484 1.20 christos !ISC_LIST_EMPTY(client->view->dlz_searched)) 1485 1.1 christos { 1486 1.1 christos dns_clientinfomethods_t cm; 1487 1.1 christos dns_clientinfo_t ci; 1488 1.1 christos dns_db_t *tdbp; 1489 1.1 christos 1490 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 1491 1.20 christos dns_clientinfo_init(&ci, client, NULL); 1492 1.20 christos dns_clientinfo_setecs(&ci, &client->ecs); 1493 1.1 christos 1494 1.1 christos tdbp = NULL; 1495 1.9 christos tresult = dns_view_searchdlz(client->view, name, zonelabels, 1496 1.9 christos &cm, &ci, &tdbp); 1497 1.9 christos /* If we successful, we found a better match. */ 1498 1.1 christos if (tresult == ISC_R_SUCCESS) { 1499 1.1 christos ns_dbversion_t *dbversion; 1500 1.1 christos 1501 1.1 christos /* 1502 1.1 christos * If the previous search returned a zone, detach it. 1503 1.1 christos */ 1504 1.9 christos if (zone != NULL) { 1505 1.1 christos dns_zone_detach(&zone); 1506 1.9 christos } 1507 1.1 christos 1508 1.1 christos /* 1509 1.1 christos * If the previous search returned a database, 1510 1.1 christos * detach it. 1511 1.1 christos */ 1512 1.9 christos if (*dbp != NULL) { 1513 1.1 christos dns_db_detach(dbp); 1514 1.9 christos } 1515 1.1 christos 1516 1.1 christos /* 1517 1.1 christos * If the previous search returned a version, clear it. 1518 1.1 christos */ 1519 1.1 christos *versionp = NULL; 1520 1.1 christos 1521 1.3 christos dbversion = ns_client_findversion(client, tdbp); 1522 1.1 christos if (dbversion == NULL) { 1523 1.1 christos tresult = ISC_R_NOMEMORY; 1524 1.1 christos } else { 1525 1.1 christos /* 1526 1.1 christos * Be sure to return our database. 1527 1.1 christos */ 1528 1.1 christos *dbp = tdbp; 1529 1.1 christos *versionp = dbversion->version; 1530 1.1 christos } 1531 1.1 christos 1532 1.1 christos /* 1533 1.1 christos * We return a null zone, No stats for DLZ zones. 1534 1.1 christos */ 1535 1.1 christos zone = NULL; 1536 1.1 christos result = tresult; 1537 1.1 christos } 1538 1.1 christos } 1539 1.1 christos 1540 1.1 christos /* If successful, Transfer ownership of zone. */ 1541 1.1 christos if (result == ISC_R_SUCCESS) { 1542 1.1 christos *zonep = zone; 1543 1.1 christos /* 1544 1.1 christos * If neither attempt above succeeded, return the cache instead 1545 1.1 christos */ 1546 1.3 christos *is_zonep = true; 1547 1.5 christos } else { 1548 1.5 christos if (result == ISC_R_NOTFOUND) { 1549 1.5 christos result = query_getcachedb(client, name, qtype, dbp, 1550 1.5 christos options); 1551 1.5 christos } 1552 1.3 christos *is_zonep = false; 1553 1.1 christos } 1554 1.23 christos return result; 1555 1.1 christos } 1556 1.1 christos 1557 1.15 christos static bool 1558 1.9 christos query_isduplicate(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, 1559 1.9 christos dns_name_t **mnamep) { 1560 1.1 christos dns_section_t section; 1561 1.1 christos dns_name_t *mname = NULL; 1562 1.1 christos isc_result_t result; 1563 1.1 christos 1564 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate"); 1565 1.1 christos 1566 1.9 christos for (section = DNS_SECTION_ANSWER; section <= DNS_SECTION_ADDITIONAL; 1567 1.16 christos section++) 1568 1.16 christos { 1569 1.9 christos result = dns_message_findname(client->message, section, name, 1570 1.9 christos type, 0, &mname, NULL); 1571 1.1 christos if (result == ISC_R_SUCCESS) { 1572 1.1 christos /* 1573 1.1 christos * We've already got this RRset in the response. 1574 1.1 christos */ 1575 1.9 christos CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: true: " 1576 1.9 christos "done"); 1577 1.23 christos return true; 1578 1.1 christos } else if (result == DNS_R_NXRRSET) { 1579 1.1 christos /* 1580 1.1 christos * The name exists, but the rdataset does not. 1581 1.1 christos */ 1582 1.9 christos if (section == DNS_SECTION_ADDITIONAL) { 1583 1.1 christos break; 1584 1.9 christos } 1585 1.9 christos } else { 1586 1.1 christos RUNTIME_CHECK(result == DNS_R_NXDOMAIN); 1587 1.9 christos } 1588 1.1 christos mname = NULL; 1589 1.1 christos } 1590 1.1 christos 1591 1.23 christos SET_IF_NOT_NULL(mnamep, mname); 1592 1.1 christos 1593 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done"); 1594 1.23 christos return false; 1595 1.1 christos } 1596 1.1 christos 1597 1.6 christos /* 1598 1.6 christos * Look up data for given 'name' and 'type' in given 'version' of 'db' for 1599 1.6 christos * 'client'. Called from query_additionalauth(). 1600 1.6 christos * 1601 1.6 christos * If the lookup is successful: 1602 1.6 christos * 1603 1.6 christos * - store the node containing the result at 'nodep', 1604 1.6 christos * 1605 1.6 christos * - store the owner name of the returned node in 'fname', 1606 1.6 christos * 1607 1.6 christos * - if 'type' is not ANY, dns_db_findext() will put the exact rdataset being 1608 1.6 christos * looked for in 'rdataset' and its signatures (if any) in 'sigrdataset', 1609 1.6 christos * 1610 1.6 christos * - if 'type' is ANY, dns_db_findext() will leave 'rdataset' and 1611 1.6 christos * 'sigrdataset' disassociated and the returned node will be iterated in 1612 1.6 christos * query_additional_cb(). 1613 1.6 christos * 1614 1.6 christos * If the lookup is not successful: 1615 1.6 christos * 1616 1.6 christos * - 'nodep' will not be written to, 1617 1.6 christos * - 'fname' may still be modified as it is passed to dns_db_findext(), 1618 1.6 christos * - 'rdataset' and 'sigrdataset' will remain disassociated. 1619 1.6 christos */ 1620 1.6 christos static isc_result_t 1621 1.6 christos query_additionalauthfind(dns_db_t *db, dns_dbversion_t *version, 1622 1.6 christos const dns_name_t *name, dns_rdatatype_t type, 1623 1.6 christos ns_client_t *client, dns_dbnode_t **nodep, 1624 1.6 christos dns_name_t *fname, dns_rdataset_t *rdataset, 1625 1.9 christos dns_rdataset_t *sigrdataset) { 1626 1.6 christos dns_clientinfomethods_t cm; 1627 1.6 christos dns_dbnode_t *node = NULL; 1628 1.6 christos dns_clientinfo_t ci; 1629 1.6 christos isc_result_t result; 1630 1.6 christos 1631 1.6 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 1632 1.20 christos dns_clientinfo_init(&ci, client, NULL); 1633 1.6 christos 1634 1.6 christos /* 1635 1.6 christos * Since we are looking for authoritative data, we do not set 1636 1.6 christos * the GLUEOK flag. Glue will be looked for later, but not 1637 1.6 christos * necessarily in the same database. 1638 1.6 christos */ 1639 1.6 christos result = dns_db_findext(db, name, version, type, 1640 1.6 christos client->query.dboptions, client->now, &node, 1641 1.6 christos fname, &cm, &ci, rdataset, sigrdataset); 1642 1.6 christos if (result != ISC_R_SUCCESS) { 1643 1.6 christos if (dns_rdataset_isassociated(rdataset)) { 1644 1.6 christos dns_rdataset_disassociate(rdataset); 1645 1.6 christos } 1646 1.6 christos 1647 1.6 christos if (sigrdataset != NULL && 1648 1.16 christos dns_rdataset_isassociated(sigrdataset)) 1649 1.16 christos { 1650 1.6 christos dns_rdataset_disassociate(sigrdataset); 1651 1.6 christos } 1652 1.6 christos 1653 1.6 christos if (node != NULL) { 1654 1.6 christos dns_db_detachnode(db, &node); 1655 1.6 christos } 1656 1.6 christos 1657 1.23 christos return result; 1658 1.6 christos } 1659 1.6 christos 1660 1.6 christos /* 1661 1.6 christos * Do not return signatures if the zone is not fully signed. 1662 1.6 christos */ 1663 1.6 christos if (sigrdataset != NULL && !dns_db_issecure(db) && 1664 1.6 christos dns_rdataset_isassociated(sigrdataset)) 1665 1.6 christos { 1666 1.6 christos dns_rdataset_disassociate(sigrdataset); 1667 1.6 christos } 1668 1.6 christos 1669 1.6 christos *nodep = node; 1670 1.6 christos 1671 1.23 christos return ISC_R_SUCCESS; 1672 1.6 christos } 1673 1.6 christos 1674 1.6 christos /* 1675 1.6 christos * For query context 'qctx', try finding authoritative additional data for 1676 1.6 christos * given 'name' and 'type'. Called from query_additional_cb(). 1677 1.6 christos * 1678 1.6 christos * If successful: 1679 1.6 christos * 1680 1.6 christos * - store pointers to the database and node which contain the result in 1681 1.6 christos * 'dbp' and 'nodep', respectively, 1682 1.6 christos * 1683 1.6 christos * - store the owner name of the returned node in 'fname', 1684 1.6 christos * 1685 1.6 christos * - potentially bind 'rdataset' and 'sigrdataset', as explained in the 1686 1.6 christos * comment for query_additionalauthfind(). 1687 1.6 christos * 1688 1.6 christos * If unsuccessful: 1689 1.6 christos * 1690 1.6 christos * - 'dbp' and 'nodep' will not be written to, 1691 1.6 christos * - 'fname' may still be modified as it is passed to dns_db_findext(), 1692 1.6 christos * - 'rdataset' and 'sigrdataset' will remain disassociated. 1693 1.6 christos */ 1694 1.6 christos static isc_result_t 1695 1.6 christos query_additionalauth(query_ctx_t *qctx, const dns_name_t *name, 1696 1.9 christos dns_rdatatype_t type, dns_db_t **dbp, dns_dbnode_t **nodep, 1697 1.9 christos dns_name_t *fname, dns_rdataset_t *rdataset, 1698 1.9 christos dns_rdataset_t *sigrdataset) { 1699 1.6 christos ns_client_t *client = qctx->client; 1700 1.6 christos ns_dbversion_t *dbversion = NULL; 1701 1.6 christos dns_dbversion_t *version = NULL; 1702 1.6 christos dns_dbnode_t *node = NULL; 1703 1.6 christos dns_zone_t *zone = NULL; 1704 1.6 christos dns_db_t *db = NULL; 1705 1.6 christos isc_result_t result; 1706 1.6 christos 1707 1.6 christos /* 1708 1.6 christos * First, look within the same zone database for authoritative 1709 1.6 christos * additional data. 1710 1.6 christos */ 1711 1.6 christos if (!client->query.authdbset || client->query.authdb == NULL) { 1712 1.23 christos return ISC_R_NOTFOUND; 1713 1.6 christos } 1714 1.6 christos 1715 1.6 christos dbversion = ns_client_findversion(client, client->query.authdb); 1716 1.6 christos if (dbversion == NULL) { 1717 1.23 christos return ISC_R_NOTFOUND; 1718 1.6 christos } 1719 1.6 christos 1720 1.6 christos dns_db_attach(client->query.authdb, &db); 1721 1.6 christos version = dbversion->version; 1722 1.6 christos 1723 1.6 christos CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: same zone"); 1724 1.6 christos 1725 1.6 christos result = query_additionalauthfind(db, version, name, type, client, 1726 1.6 christos &node, fname, rdataset, sigrdataset); 1727 1.6 christos if (result != ISC_R_SUCCESS && 1728 1.6 christos qctx->view->minimalresponses == dns_minimal_no && 1729 1.6 christos RECURSIONOK(client)) 1730 1.6 christos { 1731 1.6 christos /* 1732 1.6 christos * If we aren't doing response minimization and recursion is 1733 1.6 christos * allowed, we can try and see if any other zone matches. 1734 1.6 christos */ 1735 1.6 christos version = NULL; 1736 1.6 christos dns_db_detach(&db); 1737 1.23 christos dns_getdb_options_t options = { .nolog = true }; 1738 1.23 christos result = query_getzonedb(client, name, type, options, &zone, 1739 1.23 christos &db, &version); 1740 1.6 christos if (result != ISC_R_SUCCESS) { 1741 1.23 christos return result; 1742 1.6 christos } 1743 1.6 christos dns_zone_detach(&zone); 1744 1.6 christos 1745 1.6 christos CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: other zone"); 1746 1.6 christos 1747 1.6 christos result = query_additionalauthfind(db, version, name, type, 1748 1.6 christos client, &node, fname, 1749 1.6 christos rdataset, sigrdataset); 1750 1.6 christos } 1751 1.6 christos 1752 1.6 christos if (result != ISC_R_SUCCESS) { 1753 1.6 christos dns_db_detach(&db); 1754 1.6 christos } else { 1755 1.6 christos *nodep = node; 1756 1.6 christos node = NULL; 1757 1.6 christos 1758 1.6 christos *dbp = db; 1759 1.6 christos db = NULL; 1760 1.6 christos } 1761 1.6 christos 1762 1.23 christos return result; 1763 1.6 christos } 1764 1.6 christos 1765 1.1 christos static isc_result_t 1766 1.20 christos query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype, 1767 1.23 christos dns_rdataset_t *found DNS__DB_FLARG) { 1768 1.3 christos query_ctx_t *qctx = arg; 1769 1.3 christos ns_client_t *client = qctx->client; 1770 1.3 christos isc_result_t result, eresult = ISC_R_SUCCESS; 1771 1.3 christos dns_dbnode_t *node = NULL; 1772 1.3 christos dns_db_t *db = NULL; 1773 1.3 christos dns_name_t *fname = NULL, *mname = NULL; 1774 1.3 christos dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 1775 1.3 christos dns_rdataset_t *trdataset = NULL; 1776 1.3 christos isc_buffer_t *dbuf = NULL; 1777 1.1 christos isc_buffer_t b; 1778 1.3 christos ns_dbversion_t *dbversion = NULL; 1779 1.3 christos dns_dbversion_t *version = NULL; 1780 1.3 christos bool added_something = false, need_addname = false; 1781 1.1 christos dns_rdatatype_t type; 1782 1.1 christos dns_clientinfomethods_t cm; 1783 1.1 christos dns_clientinfo_t ci; 1784 1.3 christos dns_rdatasetadditional_t additionaltype = 1785 1.3 christos dns_rdatasetadditional_fromauth; 1786 1.1 christos 1787 1.1 christos REQUIRE(NS_CLIENT_VALID(client)); 1788 1.1 christos REQUIRE(qtype != dns_rdatatype_any); 1789 1.1 christos 1790 1.3 christos if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype)) { 1791 1.23 christos return ISC_R_SUCCESS; 1792 1.3 christos } 1793 1.1 christos 1794 1.3 christos CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb"); 1795 1.1 christos 1796 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 1797 1.20 christos dns_clientinfo_init(&ci, client, NULL); 1798 1.1 christos 1799 1.1 christos /* 1800 1.1 christos * We treat type A additional section processing as if it 1801 1.1 christos * were "any address type" additional section processing. 1802 1.1 christos * To avoid multiple lookups, we do an 'any' database 1803 1.1 christos * lookup and iterate over the node. 1804 1.1 christos */ 1805 1.3 christos if (qtype == dns_rdatatype_a) { 1806 1.1 christos type = dns_rdatatype_any; 1807 1.3 christos } else { 1808 1.1 christos type = qtype; 1809 1.3 christos } 1810 1.1 christos 1811 1.1 christos /* 1812 1.1 christos * Get some resources. 1813 1.1 christos */ 1814 1.3 christos dbuf = ns_client_getnamebuf(client); 1815 1.3 christos fname = ns_client_newname(client, dbuf, &b); 1816 1.3 christos rdataset = ns_client_newrdataset(client); 1817 1.1 christos if (WANTDNSSEC(client)) { 1818 1.3 christos sigrdataset = ns_client_newrdataset(client); 1819 1.1 christos } 1820 1.1 christos 1821 1.1 christos /* 1822 1.1 christos * If we want only minimal responses and are here, then it must 1823 1.1 christos * be for glue. 1824 1.1 christos */ 1825 1.11 christos if (qctx->view->minimalresponses == dns_minimal_yes && 1826 1.11 christos client->query.qtype != dns_rdatatype_ns) 1827 1.11 christos { 1828 1.1 christos goto try_glue; 1829 1.3 christos } 1830 1.1 christos 1831 1.1 christos /* 1832 1.6 christos * First, look for authoritative additional data. 1833 1.1 christos */ 1834 1.6 christos result = query_additionalauth(qctx, name, type, &db, &node, fname, 1835 1.6 christos rdataset, sigrdataset); 1836 1.1 christos if (result == ISC_R_SUCCESS) { 1837 1.1 christos goto found; 1838 1.1 christos } 1839 1.1 christos 1840 1.1 christos /* 1841 1.1 christos * No authoritative data was found. The cache is our next best bet. 1842 1.1 christos */ 1843 1.3 christos if (!qctx->view->recursion) { 1844 1.1 christos goto try_glue; 1845 1.3 christos } 1846 1.1 christos 1847 1.1 christos additionaltype = dns_rdatasetadditional_fromcache; 1848 1.23 christos dns_getdb_options_t options = { .nolog = true }; 1849 1.23 christos result = query_getcachedb(client, name, qtype, &db, options); 1850 1.1 christos if (result != ISC_R_SUCCESS) { 1851 1.1 christos /* 1852 1.1 christos * Most likely the client isn't allowed to query the cache. 1853 1.1 christos */ 1854 1.1 christos goto try_glue; 1855 1.1 christos } 1856 1.1 christos /* 1857 1.1 christos * Attempt to validate glue. 1858 1.1 christos */ 1859 1.1 christos if (sigrdataset == NULL) { 1860 1.3 christos sigrdataset = ns_client_newrdataset(client); 1861 1.1 christos } 1862 1.1 christos 1863 1.1 christos version = NULL; 1864 1.1 christos result = dns_db_findext(db, name, version, type, 1865 1.9 christos client->query.dboptions | DNS_DBFIND_GLUEOK | 1866 1.9 christos DNS_DBFIND_ADDITIONALOK, 1867 1.9 christos client->now, &node, fname, &cm, &ci, rdataset, 1868 1.9 christos sigrdataset); 1869 1.1 christos 1870 1.3 christos dns_cache_updatestats(qctx->view->cache, result); 1871 1.3 christos if (!WANTDNSSEC(client)) { 1872 1.3 christos ns_client_putrdataset(client, &sigrdataset); 1873 1.3 christos } 1874 1.9 christos if (result == ISC_R_SUCCESS) { 1875 1.1 christos goto found; 1876 1.9 christos } 1877 1.1 christos 1878 1.3 christos if (dns_rdataset_isassociated(rdataset)) { 1879 1.1 christos dns_rdataset_disassociate(rdataset); 1880 1.3 christos } 1881 1.3 christos if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { 1882 1.1 christos dns_rdataset_disassociate(sigrdataset); 1883 1.3 christos } 1884 1.3 christos if (node != NULL) { 1885 1.1 christos dns_db_detachnode(db, &node); 1886 1.3 christos } 1887 1.1 christos dns_db_detach(&db); 1888 1.1 christos 1889 1.9 christos try_glue: 1890 1.1 christos /* 1891 1.1 christos * No cached data was found. Glue is our last chance. 1892 1.1 christos * RFC1035 sayeth: 1893 1.1 christos * 1894 1.1 christos * NS records cause both the usual additional section 1895 1.1 christos * processing to locate a type A record, and, when used 1896 1.1 christos * in a referral, a special search of the zone in which 1897 1.1 christos * they reside for glue information. 1898 1.1 christos * 1899 1.1 christos * This is the "special search". Note that we must search 1900 1.1 christos * the zone where the NS record resides, not the zone it 1901 1.1 christos * points to, and that we only do the search in the delegation 1902 1.1 christos * case (identified by client->query.gluedb being set). 1903 1.1 christos */ 1904 1.1 christos 1905 1.3 christos if (client->query.gluedb == NULL) { 1906 1.1 christos goto cleanup; 1907 1.3 christos } 1908 1.1 christos 1909 1.1 christos /* 1910 1.1 christos * Don't poison caches using the bailiwick protection model. 1911 1.1 christos */ 1912 1.3 christos if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) { 1913 1.1 christos goto cleanup; 1914 1.3 christos } 1915 1.1 christos 1916 1.3 christos dbversion = ns_client_findversion(client, client->query.gluedb); 1917 1.3 christos if (dbversion == NULL) { 1918 1.1 christos goto cleanup; 1919 1.3 christos } 1920 1.1 christos 1921 1.1 christos dns_db_attach(client->query.gluedb, &db); 1922 1.1 christos version = dbversion->version; 1923 1.1 christos additionaltype = dns_rdatasetadditional_fromglue; 1924 1.1 christos result = dns_db_findext(db, name, version, type, 1925 1.1 christos client->query.dboptions | DNS_DBFIND_GLUEOK, 1926 1.9 christos client->now, &node, fname, &cm, &ci, rdataset, 1927 1.9 christos sigrdataset); 1928 1.9 christos if (result != ISC_R_SUCCESS && result != DNS_R_ZONECUT && 1929 1.16 christos result != DNS_R_GLUE) 1930 1.16 christos { 1931 1.1 christos goto cleanup; 1932 1.3 christos } 1933 1.1 christos 1934 1.9 christos found: 1935 1.1 christos /* 1936 1.1 christos * We have found a potential additional data rdataset, or 1937 1.1 christos * at least a node to iterate over. 1938 1.1 christos */ 1939 1.3 christos ns_client_keepname(client, fname, dbuf); 1940 1.1 christos 1941 1.1 christos /* 1942 1.20 christos * Does the caller want the found rdataset? 1943 1.20 christos */ 1944 1.20 christos if (found != NULL && dns_rdataset_isassociated(rdataset)) { 1945 1.20 christos dns_rdataset_clone(rdataset, found); 1946 1.20 christos } 1947 1.20 christos 1948 1.20 christos /* 1949 1.1 christos * If we have an rdataset, add it to the additional data 1950 1.1 christos * section. 1951 1.1 christos */ 1952 1.1 christos mname = NULL; 1953 1.1 christos if (dns_rdataset_isassociated(rdataset) && 1954 1.3 christos !query_isduplicate(client, fname, type, &mname)) 1955 1.3 christos { 1956 1.1 christos if (mname != NULL) { 1957 1.1 christos INSIST(mname != fname); 1958 1.3 christos ns_client_releasename(client, &fname); 1959 1.1 christos fname = mname; 1960 1.3 christos } else { 1961 1.3 christos need_addname = true; 1962 1.3 christos } 1963 1.1 christos ISC_LIST_APPEND(fname->list, rdataset, link); 1964 1.1 christos trdataset = rdataset; 1965 1.1 christos rdataset = NULL; 1966 1.3 christos added_something = true; 1967 1.1 christos /* 1968 1.1 christos * Note: we only add SIGs if we've added the type they cover, 1969 1.1 christos * so we do not need to check if the SIG rdataset is already 1970 1.1 christos * in the response. 1971 1.1 christos */ 1972 1.1 christos if (sigrdataset != NULL && 1973 1.16 christos dns_rdataset_isassociated(sigrdataset)) 1974 1.16 christos { 1975 1.1 christos ISC_LIST_APPEND(fname->list, sigrdataset, link); 1976 1.1 christos sigrdataset = NULL; 1977 1.1 christos } 1978 1.1 christos } 1979 1.1 christos 1980 1.1 christos if (qtype == dns_rdatatype_a) { 1981 1.1 christos /* 1982 1.1 christos * We now go looking for A and AAAA records, along with 1983 1.1 christos * their signatures. 1984 1.1 christos * 1985 1.1 christos * XXXRTH This code could be more efficient. 1986 1.1 christos */ 1987 1.1 christos if (rdataset != NULL) { 1988 1.3 christos if (dns_rdataset_isassociated(rdataset)) { 1989 1.1 christos dns_rdataset_disassociate(rdataset); 1990 1.3 christos } 1991 1.1 christos } else { 1992 1.3 christos rdataset = ns_client_newrdataset(client); 1993 1.1 christos } 1994 1.1 christos if (sigrdataset != NULL) { 1995 1.3 christos if (dns_rdataset_isassociated(sigrdataset)) { 1996 1.1 christos dns_rdataset_disassociate(sigrdataset); 1997 1.3 christos } 1998 1.1 christos } else if (WANTDNSSEC(client)) { 1999 1.3 christos sigrdataset = ns_client_newrdataset(client); 2000 1.1 christos } 2001 1.3 christos if (query_isduplicate(client, fname, dns_rdatatype_a, NULL)) { 2002 1.1 christos goto aaaa_lookup; 2003 1.3 christos } 2004 1.9 christos result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 2005 1.9 christos 0, client->now, rdataset, 2006 1.9 christos sigrdataset); 2007 1.1 christos if (result == DNS_R_NCACHENXDOMAIN) { 2008 1.1 christos goto addname; 2009 1.1 christos } else if (result == DNS_R_NCACHENXRRSET) { 2010 1.1 christos dns_rdataset_disassociate(rdataset); 2011 1.1 christos if (sigrdataset != NULL && 2012 1.16 christos dns_rdataset_isassociated(sigrdataset)) 2013 1.16 christos { 2014 1.1 christos dns_rdataset_disassociate(sigrdataset); 2015 1.3 christos } 2016 1.1 christos } else if (result == ISC_R_SUCCESS) { 2017 1.3 christos bool invalid = false; 2018 1.1 christos mname = NULL; 2019 1.1 christos if (additionaltype == 2020 1.9 christos dns_rdatasetadditional_fromcache && 2021 1.1 christos (DNS_TRUST_PENDING(rdataset->trust) || 2022 1.1 christos DNS_TRUST_GLUE(rdataset->trust))) 2023 1.1 christos { 2024 1.1 christos /* validate() may change rdataset->trust */ 2025 1.9 christos invalid = !validate(client, db, fname, rdataset, 2026 1.9 christos sigrdataset); 2027 1.1 christos } 2028 1.1 christos if (invalid && DNS_TRUST_PENDING(rdataset->trust)) { 2029 1.1 christos dns_rdataset_disassociate(rdataset); 2030 1.1 christos if (sigrdataset != NULL && 2031 1.16 christos dns_rdataset_isassociated(sigrdataset)) 2032 1.16 christos { 2033 1.1 christos dns_rdataset_disassociate(sigrdataset); 2034 1.3 christos } 2035 1.1 christos } else if (!query_isduplicate(client, fname, 2036 1.9 christos dns_rdatatype_a, &mname)) 2037 1.9 christos { 2038 1.1 christos if (mname != fname) { 2039 1.1 christos if (mname != NULL) { 2040 1.3 christos ns_client_releasename(client, 2041 1.3 christos &fname); 2042 1.1 christos fname = mname; 2043 1.3 christos } else { 2044 1.3 christos need_addname = true; 2045 1.3 christos } 2046 1.1 christos } 2047 1.1 christos ISC_LIST_APPEND(fname->list, rdataset, link); 2048 1.3 christos added_something = true; 2049 1.1 christos if (sigrdataset != NULL && 2050 1.16 christos dns_rdataset_isassociated(sigrdataset)) 2051 1.16 christos { 2052 1.1 christos ISC_LIST_APPEND(fname->list, 2053 1.1 christos sigrdataset, link); 2054 1.1 christos sigrdataset = 2055 1.3 christos ns_client_newrdataset(client); 2056 1.1 christos } 2057 1.3 christos rdataset = ns_client_newrdataset(client); 2058 1.1 christos } else { 2059 1.1 christos dns_rdataset_disassociate(rdataset); 2060 1.1 christos if (sigrdataset != NULL && 2061 1.16 christos dns_rdataset_isassociated(sigrdataset)) 2062 1.16 christos { 2063 1.1 christos dns_rdataset_disassociate(sigrdataset); 2064 1.3 christos } 2065 1.1 christos } 2066 1.1 christos } 2067 1.9 christos aaaa_lookup: 2068 1.1 christos if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL)) 2069 1.3 christos { 2070 1.1 christos goto addname; 2071 1.3 christos } 2072 1.1 christos result = dns_db_findrdataset(db, node, version, 2073 1.9 christos dns_rdatatype_aaaa, 0, client->now, 2074 1.1 christos rdataset, sigrdataset); 2075 1.1 christos if (result == DNS_R_NCACHENXDOMAIN) { 2076 1.1 christos goto addname; 2077 1.1 christos } else if (result == DNS_R_NCACHENXRRSET) { 2078 1.1 christos dns_rdataset_disassociate(rdataset); 2079 1.1 christos if (sigrdataset != NULL && 2080 1.16 christos dns_rdataset_isassociated(sigrdataset)) 2081 1.16 christos { 2082 1.1 christos dns_rdataset_disassociate(sigrdataset); 2083 1.3 christos } 2084 1.1 christos } else if (result == ISC_R_SUCCESS) { 2085 1.3 christos bool invalid = false; 2086 1.1 christos mname = NULL; 2087 1.3 christos 2088 1.1 christos if (additionaltype == 2089 1.9 christos dns_rdatasetadditional_fromcache && 2090 1.1 christos (DNS_TRUST_PENDING(rdataset->trust) || 2091 1.1 christos DNS_TRUST_GLUE(rdataset->trust))) 2092 1.1 christos { 2093 1.1 christos /* validate() may change rdataset->trust */ 2094 1.9 christos invalid = !validate(client, db, fname, rdataset, 2095 1.9 christos sigrdataset); 2096 1.1 christos } 2097 1.1 christos 2098 1.1 christos if (invalid && DNS_TRUST_PENDING(rdataset->trust)) { 2099 1.1 christos dns_rdataset_disassociate(rdataset); 2100 1.1 christos if (sigrdataset != NULL && 2101 1.16 christos dns_rdataset_isassociated(sigrdataset)) 2102 1.16 christos { 2103 1.1 christos dns_rdataset_disassociate(sigrdataset); 2104 1.3 christos } 2105 1.1 christos } else if (!query_isduplicate(client, fname, 2106 1.9 christos dns_rdatatype_aaaa, 2107 1.16 christos &mname)) 2108 1.16 christos { 2109 1.1 christos if (mname != fname) { 2110 1.1 christos if (mname != NULL) { 2111 1.3 christos ns_client_releasename(client, 2112 1.3 christos &fname); 2113 1.1 christos fname = mname; 2114 1.3 christos } else { 2115 1.3 christos need_addname = true; 2116 1.3 christos } 2117 1.1 christos } 2118 1.1 christos ISC_LIST_APPEND(fname->list, rdataset, link); 2119 1.3 christos added_something = true; 2120 1.1 christos if (sigrdataset != NULL && 2121 1.16 christos dns_rdataset_isassociated(sigrdataset)) 2122 1.16 christos { 2123 1.1 christos ISC_LIST_APPEND(fname->list, 2124 1.1 christos sigrdataset, link); 2125 1.1 christos sigrdataset = NULL; 2126 1.1 christos } 2127 1.1 christos rdataset = NULL; 2128 1.1 christos } 2129 1.1 christos } 2130 1.1 christos } 2131 1.1 christos 2132 1.9 christos addname: 2133 1.3 christos CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: addname"); 2134 1.1 christos /* 2135 1.1 christos * If we haven't added anything, then we're done. 2136 1.1 christos */ 2137 1.3 christos if (!added_something) { 2138 1.1 christos goto cleanup; 2139 1.3 christos } 2140 1.1 christos 2141 1.1 christos /* 2142 1.1 christos * We may have added our rdatasets to an existing name, if so, then 2143 1.3 christos * need_addname will be false. Whether we used an existing name 2144 1.1 christos * or a new one, we must set fname to NULL to prevent cleanup. 2145 1.1 christos */ 2146 1.3 christos if (need_addname) { 2147 1.1 christos dns_message_addname(client->message, fname, 2148 1.1 christos DNS_SECTION_ADDITIONAL); 2149 1.3 christos } 2150 1.1 christos 2151 1.1 christos /* 2152 1.15 christos * In some cases, a record that has been added as additional 2153 1.15 christos * data may *also* trigger the addition of additional data. 2154 1.22 christos * This cannot go more than 'max-restarts' levels deep. 2155 1.15 christos */ 2156 1.15 christos if (trdataset != NULL && dns_rdatatype_followadditional(type)) { 2157 1.22 christos if (client->additionaldepth++ < client->view->max_restarts) { 2158 1.20 christos eresult = dns_rdataset_additionaldata( 2159 1.24 christos trdataset, fname, query_additional_cb, qctx, 2160 1.24 christos DNS_RDATASET_MAXADDITIONAL); 2161 1.20 christos } 2162 1.20 christos client->additionaldepth--; 2163 1.1 christos } 2164 1.1 christos 2165 1.20 christos /* 2166 1.20 christos * Don't release fname. 2167 1.20 christos */ 2168 1.20 christos fname = NULL; 2169 1.20 christos 2170 1.9 christos cleanup: 2171 1.3 christos CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: cleanup"); 2172 1.3 christos ns_client_putrdataset(client, &rdataset); 2173 1.3 christos if (sigrdataset != NULL) { 2174 1.3 christos ns_client_putrdataset(client, &sigrdataset); 2175 1.3 christos } 2176 1.3 christos if (fname != NULL) { 2177 1.3 christos ns_client_releasename(client, &fname); 2178 1.3 christos } 2179 1.3 christos if (node != NULL) { 2180 1.1 christos dns_db_detachnode(db, &node); 2181 1.3 christos } 2182 1.3 christos if (db != NULL) { 2183 1.1 christos dns_db_detach(&db); 2184 1.3 christos } 2185 1.1 christos 2186 1.3 christos CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: done"); 2187 1.23 christos return eresult; 2188 1.1 christos } 2189 1.1 christos 2190 1.3 christos /* 2191 1.3 christos * Add 'rdataset' to 'name'. 2192 1.3 christos */ 2193 1.15 christos static void 2194 1.3 christos query_addtoname(dns_name_t *name, dns_rdataset_t *rdataset) { 2195 1.3 christos ISC_LIST_APPEND(name->list, rdataset, link); 2196 1.3 christos } 2197 1.3 christos 2198 1.3 christos /* 2199 1.3 christos * Set the ordering for 'rdataset'. 2200 1.3 christos */ 2201 1.1 christos static void 2202 1.3 christos query_setorder(query_ctx_t *qctx, dns_name_t *name, dns_rdataset_t *rdataset) { 2203 1.3 christos ns_client_t *client = qctx->client; 2204 1.3 christos dns_order_t *order = client->view->order; 2205 1.1 christos 2206 1.3 christos CTRACE(ISC_LOG_DEBUG(3), "query_setorder"); 2207 1.1 christos 2208 1.3 christos UNUSED(client); 2209 1.1 christos 2210 1.3 christos if (order != NULL) { 2211 1.9 christos rdataset->attributes |= dns_order_find( 2212 1.9 christos order, name, rdataset->type, rdataset->rdclass); 2213 1.3 christos } 2214 1.1 christos rdataset->attributes |= DNS_RDATASETATTR_LOADORDER; 2215 1.9 christos } 2216 1.3 christos 2217 1.3 christos /* 2218 1.3 christos * Handle glue and fetch any other needed additional data for 'rdataset'. 2219 1.3 christos */ 2220 1.3 christos static void 2221 1.20 christos query_additional(query_ctx_t *qctx, dns_name_t *name, 2222 1.20 christos dns_rdataset_t *rdataset) { 2223 1.3 christos ns_client_t *client = qctx->client; 2224 1.3 christos isc_result_t result; 2225 1.3 christos 2226 1.3 christos CTRACE(ISC_LOG_DEBUG(3), "query_additional"); 2227 1.1 christos 2228 1.3 christos if (NOADDITIONAL(client)) { 2229 1.1 christos return; 2230 1.3 christos } 2231 1.1 christos 2232 1.1 christos /* 2233 1.1 christos * Try to process glue directly. 2234 1.1 christos */ 2235 1.23 christos if (rdataset->type == dns_rdatatype_ns && 2236 1.23 christos client->query.gluedb != NULL && dns_db_iszone(client->query.gluedb)) 2237 1.1 christos { 2238 1.23 christos ns_dbversion_t *dbversion = NULL; 2239 1.1 christos 2240 1.3 christos dbversion = ns_client_findversion(client, client->query.gluedb); 2241 1.3 christos if (dbversion == NULL) { 2242 1.1 christos goto regular; 2243 1.1 christos } 2244 1.1 christos 2245 1.23 christos result = dns_db_addglue(qctx->db, dbversion->version, rdataset, 2246 1.23 christos client->message); 2247 1.3 christos if (result == ISC_R_SUCCESS) { 2248 1.1 christos return; 2249 1.3 christos } 2250 1.1 christos } 2251 1.1 christos 2252 1.9 christos regular: 2253 1.1 christos /* 2254 1.3 christos * Add other additional data if needed. 2255 1.1 christos * We don't care if dns_rdataset_additionaldata() fails. 2256 1.1 christos */ 2257 1.20 christos (void)dns_rdataset_additionaldata(rdataset, name, query_additional_cb, 2258 1.24 christos qctx, DNS_RDATASET_MAXADDITIONAL); 2259 1.3 christos CTRACE(ISC_LOG_DEBUG(3), "query_additional: done"); 2260 1.1 christos } 2261 1.1 christos 2262 1.1 christos static void 2263 1.3 christos query_addrrset(query_ctx_t *qctx, dns_name_t **namep, 2264 1.1 christos dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp, 2265 1.9 christos isc_buffer_t *dbuf, dns_section_t section) { 2266 1.3 christos isc_result_t result; 2267 1.3 christos ns_client_t *client = qctx->client; 2268 1.1 christos dns_name_t *name = *namep, *mname = NULL; 2269 1.1 christos dns_rdataset_t *rdataset = *rdatasetp, *mrdataset = NULL; 2270 1.1 christos dns_rdataset_t *sigrdataset = NULL; 2271 1.1 christos 2272 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addrrset"); 2273 1.1 christos 2274 1.3 christos REQUIRE(name != NULL); 2275 1.3 christos 2276 1.3 christos if (sigrdatasetp != NULL) { 2277 1.1 christos sigrdataset = *sigrdatasetp; 2278 1.3 christos } 2279 1.1 christos 2280 1.1 christos /*% 2281 1.1 christos * To the current response for 'client', add the answer RRset 2282 1.1 christos * '*rdatasetp' and an optional signature set '*sigrdatasetp', with 2283 1.1 christos * owner name '*namep', to section 'section', unless they are 2284 1.24 christos * already there. Also add any pertinent additional data, unless 2285 1.24 christos * the query was for type ANY. 2286 1.1 christos * 2287 1.1 christos * If 'dbuf' is not NULL, then '*namep' is the name whose data is 2288 1.1 christos * stored in 'dbuf'. In this case, query_addrrset() guarantees that 2289 1.1 christos * when it returns the name will either have been kept or released. 2290 1.1 christos */ 2291 1.9 christos result = dns_message_findname(client->message, section, name, 2292 1.9 christos rdataset->type, rdataset->covers, &mname, 2293 1.9 christos &mrdataset); 2294 1.1 christos if (result == ISC_R_SUCCESS) { 2295 1.1 christos /* 2296 1.1 christos * We've already got an RRset of the given name and type. 2297 1.1 christos */ 2298 1.9 christos CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: dns_message_findname " 2299 1.9 christos "succeeded: done"); 2300 1.3 christos if (dbuf != NULL) { 2301 1.3 christos ns_client_releasename(client, namep); 2302 1.3 christos } 2303 1.3 christos if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0) { 2304 1.1 christos mrdataset->attributes |= DNS_RDATASETATTR_REQUIRED; 2305 1.3 christos } 2306 1.1 christos return; 2307 1.1 christos } else if (result == DNS_R_NXDOMAIN) { 2308 1.1 christos /* 2309 1.1 christos * The name doesn't exist. 2310 1.1 christos */ 2311 1.3 christos if (dbuf != NULL) { 2312 1.3 christos ns_client_keepname(client, name, dbuf); 2313 1.3 christos } 2314 1.1 christos dns_message_addname(client->message, name, section); 2315 1.1 christos *namep = NULL; 2316 1.1 christos mname = name; 2317 1.1 christos } else { 2318 1.1 christos RUNTIME_CHECK(result == DNS_R_NXRRSET); 2319 1.3 christos if (dbuf != NULL) { 2320 1.3 christos ns_client_releasename(client, namep); 2321 1.3 christos } 2322 1.1 christos } 2323 1.1 christos 2324 1.1 christos if (rdataset->trust != dns_trust_secure && 2325 1.9 christos (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY)) 2326 1.3 christos { 2327 1.1 christos client->query.attributes &= ~NS_QUERYATTR_SECURE; 2328 1.3 christos } 2329 1.3 christos 2330 1.3 christos /* 2331 1.3 christos * Update message name, set rdataset order, and do additional 2332 1.3 christos * section processing if needed. 2333 1.3 christos */ 2334 1.3 christos query_addtoname(mname, rdataset); 2335 1.3 christos query_setorder(qctx, mname, rdataset); 2336 1.26 christos if (qctx->qtype != dns_rdatatype_any || 2337 1.26 christos (!qctx->authoritative && section == DNS_SECTION_AUTHORITY && 2338 1.26 christos rdataset->type == dns_rdatatype_ns)) 2339 1.26 christos { 2340 1.24 christos query_additional(qctx, mname, rdataset); 2341 1.24 christos } 2342 1.1 christos 2343 1.1 christos /* 2344 1.1 christos * Note: we only add SIGs if we've added the type they cover, so 2345 1.1 christos * we do not need to check if the SIG rdataset is already in the 2346 1.1 christos * response. 2347 1.1 christos */ 2348 1.1 christos *rdatasetp = NULL; 2349 1.1 christos if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { 2350 1.1 christos /* 2351 1.1 christos * We have a signature. Add it to the response. 2352 1.1 christos */ 2353 1.1 christos ISC_LIST_APPEND(mname->list, sigrdataset, link); 2354 1.1 christos *sigrdatasetp = NULL; 2355 1.1 christos } 2356 1.1 christos 2357 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done"); 2358 1.1 christos } 2359 1.1 christos 2360 1.1 christos /* 2361 1.1 christos * Mark the RRsets as secure. Update the cache (db) to reflect the 2362 1.1 christos * change in trust level. 2363 1.1 christos */ 2364 1.1 christos static void 2365 1.1 christos mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name, 2366 1.1 christos dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset, 2367 1.9 christos dns_rdataset_t *sigrdataset) { 2368 1.1 christos isc_result_t result; 2369 1.1 christos dns_dbnode_t *node = NULL; 2370 1.1 christos dns_clientinfomethods_t cm; 2371 1.1 christos dns_clientinfo_t ci; 2372 1.1 christos isc_stdtime_t now; 2373 1.1 christos 2374 1.1 christos rdataset->trust = dns_trust_secure; 2375 1.1 christos sigrdataset->trust = dns_trust_secure; 2376 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 2377 1.20 christos dns_clientinfo_init(&ci, client, NULL); 2378 1.1 christos 2379 1.1 christos /* 2380 1.1 christos * Save the updated secure state. Ignore failures. 2381 1.1 christos */ 2382 1.3 christos result = dns_db_findnodeext(db, name, true, &cm, &ci, &node); 2383 1.9 christos if (result != ISC_R_SUCCESS) { 2384 1.1 christos return; 2385 1.9 christos } 2386 1.1 christos 2387 1.23 christos now = isc_stdtime_now(); 2388 1.1 christos dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now, 2389 1.1 christos client->view->acceptexpired); 2390 1.1 christos 2391 1.9 christos (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset, 0, 2392 1.9 christos NULL); 2393 1.9 christos (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset, 0, 2394 1.9 christos NULL); 2395 1.1 christos dns_db_detachnode(db, &node); 2396 1.1 christos } 2397 1.1 christos 2398 1.1 christos /* 2399 1.1 christos * Find the secure key that corresponds to rrsig. 2400 1.1 christos * Note: 'keyrdataset' maintains state between successive calls, 2401 1.1 christos * there may be multiple keys with the same keyid. 2402 1.3 christos * Return false if we have exhausted all the possible keys. 2403 1.1 christos */ 2404 1.3 christos static bool 2405 1.1 christos get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig, 2406 1.9 christos dns_rdataset_t *keyrdataset, dst_key_t **keyp) { 2407 1.1 christos isc_result_t result; 2408 1.1 christos dns_dbnode_t *node = NULL; 2409 1.3 christos bool secure = false; 2410 1.1 christos dns_clientinfomethods_t cm; 2411 1.1 christos dns_clientinfo_t ci; 2412 1.1 christos 2413 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 2414 1.20 christos dns_clientinfo_init(&ci, client, NULL); 2415 1.1 christos 2416 1.1 christos if (!dns_rdataset_isassociated(keyrdataset)) { 2417 1.9 christos result = dns_db_findnodeext(db, &rrsig->signer, false, &cm, &ci, 2418 1.9 christos &node); 2419 1.9 christos if (result != ISC_R_SUCCESS) { 2420 1.23 christos return false; 2421 1.9 christos } 2422 1.1 christos 2423 1.1 christos result = dns_db_findrdataset(db, node, NULL, 2424 1.1 christos dns_rdatatype_dnskey, 0, 2425 1.1 christos client->now, keyrdataset, NULL); 2426 1.1 christos dns_db_detachnode(db, &node); 2427 1.9 christos if (result != ISC_R_SUCCESS) { 2428 1.23 christos return false; 2429 1.9 christos } 2430 1.1 christos 2431 1.9 christos if (keyrdataset->trust != dns_trust_secure) { 2432 1.23 christos return false; 2433 1.9 christos } 2434 1.1 christos 2435 1.1 christos result = dns_rdataset_first(keyrdataset); 2436 1.9 christos } else { 2437 1.1 christos result = dns_rdataset_next(keyrdataset); 2438 1.9 christos } 2439 1.1 christos 2440 1.9 christos for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset)) 2441 1.9 christos { 2442 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 2443 1.1 christos isc_buffer_t b; 2444 1.1 christos 2445 1.1 christos dns_rdataset_current(keyrdataset, &rdata); 2446 1.1 christos isc_buffer_init(&b, rdata.data, rdata.length); 2447 1.1 christos isc_buffer_add(&b, rdata.length); 2448 1.1 christos result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b, 2449 1.23 christos client->manager->mctx, keyp); 2450 1.9 christos if (result != ISC_R_SUCCESS) { 2451 1.1 christos continue; 2452 1.9 christos } 2453 1.1 christos if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) && 2454 1.1 christos rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) && 2455 1.9 christos dst_key_iszonekey(*keyp)) 2456 1.9 christos { 2457 1.3 christos secure = true; 2458 1.1 christos break; 2459 1.1 christos } 2460 1.1 christos dst_key_free(keyp); 2461 1.1 christos } 2462 1.23 christos return secure; 2463 1.1 christos } 2464 1.1 christos 2465 1.3 christos static bool 2466 1.1 christos verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset, 2467 1.9 christos dns_rdata_t *rdata, ns_client_t *client) { 2468 1.1 christos isc_result_t result; 2469 1.1 christos dns_fixedname_t fixed; 2470 1.3 christos bool ignore = false; 2471 1.1 christos 2472 1.1 christos dns_fixedname_init(&fixed); 2473 1.1 christos 2474 1.1 christos again: 2475 1.3 christos result = dns_dnssec_verify(name, rdataset, key, ignore, 2476 1.23 christos client->view->maxbits, client->manager->mctx, 2477 1.23 christos rdata, NULL); 2478 1.1 christos if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) { 2479 1.3 christos ignore = true; 2480 1.1 christos goto again; 2481 1.1 christos } 2482 1.9 christos if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) { 2483 1.23 christos return true; 2484 1.9 christos } 2485 1.23 christos return false; 2486 1.1 christos } 2487 1.1 christos 2488 1.1 christos /* 2489 1.1 christos * Validate the rdataset if possible with available records. 2490 1.1 christos */ 2491 1.3 christos static bool 2492 1.1 christos validate(ns_client_t *client, dns_db_t *db, dns_name_t *name, 2493 1.9 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 2494 1.1 christos isc_result_t result; 2495 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 2496 1.1 christos dns_rdata_rrsig_t rrsig; 2497 1.1 christos dst_key_t *key = NULL; 2498 1.1 christos dns_rdataset_t keyrdataset; 2499 1.1 christos 2500 1.9 christos if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) { 2501 1.23 christos return false; 2502 1.9 christos } 2503 1.1 christos 2504 1.9 christos for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS; 2505 1.9 christos result = dns_rdataset_next(sigrdataset)) 2506 1.9 christos { 2507 1.1 christos dns_rdata_reset(&rdata); 2508 1.1 christos dns_rdataset_current(sigrdataset, &rdata); 2509 1.1 christos result = dns_rdata_tostruct(&rdata, &rrsig, NULL); 2510 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 2511 1.1 christos if (!dns_resolver_algorithm_supported(client->view->resolver, 2512 1.26 christos &rrsig.signer, 2513 1.26 christos rrsig.algorithm)) 2514 1.9 christos { 2515 1.24 christos char txt[DNS_NAME_FORMATSIZE + 32]; 2516 1.24 christos isc_buffer_t buffer; 2517 1.24 christos 2518 1.24 christos isc_buffer_init(&buffer, txt, sizeof(txt)); 2519 1.24 christos dns_secalg_totext(rrsig.algorithm, &buffer); 2520 1.24 christos isc_buffer_putstr(&buffer, " "); 2521 1.24 christos dns_name_totext(name, DNS_NAME_OMITFINALDOT, &buffer); 2522 1.24 christos isc_buffer_putstr(&buffer, " (cached)"); 2523 1.24 christos isc_buffer_putuint8(&buffer, 0); 2524 1.24 christos 2525 1.24 christos dns_ede_add(&client->edectx, DNS_EDE_DNSKEYALG, 2526 1.24 christos isc_buffer_base(&buffer)); 2527 1.1 christos continue; 2528 1.9 christos } 2529 1.9 christos if (!dns_name_issubdomain(name, &rrsig.signer)) { 2530 1.1 christos continue; 2531 1.9 christos } 2532 1.1 christos dns_rdataset_init(&keyrdataset); 2533 1.1 christos do { 2534 1.9 christos if (!get_key(client, db, &rrsig, &keyrdataset, &key)) { 2535 1.1 christos break; 2536 1.9 christos } 2537 1.1 christos if (verify(key, name, rdataset, &rdata, client)) { 2538 1.1 christos dst_key_free(&key); 2539 1.1 christos dns_rdataset_disassociate(&keyrdataset); 2540 1.9 christos mark_secure(client, db, name, &rrsig, rdataset, 2541 1.9 christos sigrdataset); 2542 1.23 christos return true; 2543 1.1 christos } 2544 1.1 christos dst_key_free(&key); 2545 1.1 christos } while (1); 2546 1.9 christos if (dns_rdataset_isassociated(&keyrdataset)) { 2547 1.1 christos dns_rdataset_disassociate(&keyrdataset); 2548 1.9 christos } 2549 1.1 christos } 2550 1.23 christos return false; 2551 1.1 christos } 2552 1.1 christos 2553 1.1 christos static void 2554 1.1 christos fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) { 2555 1.9 christos if (*rdataset == NULL) { 2556 1.3 christos *rdataset = ns_client_newrdataset(client); 2557 1.9 christos } else if (dns_rdataset_isassociated(*rdataset)) { 2558 1.1 christos dns_rdataset_disassociate(*rdataset); 2559 1.9 christos } 2560 1.1 christos } 2561 1.1 christos 2562 1.1 christos static void 2563 1.1 christos fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf, 2564 1.9 christos isc_buffer_t *nbuf) { 2565 1.1 christos if (*fname == NULL) { 2566 1.3 christos *dbuf = ns_client_getnamebuf(client); 2567 1.3 christos *fname = ns_client_newname(client, *dbuf, nbuf); 2568 1.1 christos } 2569 1.1 christos } 2570 1.1 christos 2571 1.1 christos static void 2572 1.23 christos free_fresp(ns_client_t *client, dns_fetchresponse_t **frespp) { 2573 1.23 christos dns_fetchresponse_t *fresp = *frespp; 2574 1.1 christos 2575 1.23 christos CTRACE(ISC_LOG_DEBUG(3), "free_fresp"); 2576 1.9 christos 2577 1.23 christos if (fresp->fetch != NULL) { 2578 1.23 christos dns_resolver_destroyfetch(&fresp->fetch); 2579 1.23 christos } 2580 1.23 christos if (fresp->node != NULL) { 2581 1.23 christos dns_db_detachnode(fresp->db, &fresp->node); 2582 1.3 christos } 2583 1.23 christos if (fresp->db != NULL) { 2584 1.23 christos dns_db_detach(&fresp->db); 2585 1.3 christos } 2586 1.23 christos if (fresp->rdataset != NULL) { 2587 1.23 christos ns_client_putrdataset(client, &fresp->rdataset); 2588 1.3 christos } 2589 1.23 christos if (fresp->sigrdataset != NULL) { 2590 1.23 christos ns_client_putrdataset(client, &fresp->sigrdataset); 2591 1.3 christos } 2592 1.23 christos 2593 1.24 christos dns_resolver_freefresp(frespp); 2594 1.23 christos } 2595 1.23 christos 2596 1.23 christos static isc_result_t 2597 1.23 christos recursionquotatype_attach(ns_client_t *client, bool soft_limit) { 2598 1.23 christos isc_statscounter_t recurscount; 2599 1.23 christos isc_result_t result; 2600 1.23 christos 2601 1.23 christos result = isc_quota_acquire(&client->manager->sctx->recursionquota); 2602 1.23 christos switch (result) { 2603 1.23 christos case ISC_R_SUCCESS: 2604 1.23 christos break; 2605 1.23 christos case ISC_R_SOFTQUOTA: 2606 1.23 christos if (soft_limit) { 2607 1.23 christos /* 2608 1.23 christos * Exceeding soft quota was allowed, so continue as if 2609 1.23 christos * 'result' was ISC_R_SUCCESS while retaining the 2610 1.23 christos * original result code. 2611 1.23 christos */ 2612 1.23 christos break; 2613 1.23 christos } 2614 1.23 christos 2615 1.23 christos isc_quota_release(&client->manager->sctx->recursionquota); 2616 1.23 christos FALLTHROUGH; 2617 1.23 christos default: 2618 1.23 christos return result; 2619 1.3 christos } 2620 1.9 christos 2621 1.23 christos recurscount = ns_stats_increment(client->manager->sctx->nsstats, 2622 1.23 christos ns_statscounter_recursclients); 2623 1.23 christos 2624 1.23 christos ns_stats_update_if_greater(client->manager->sctx->nsstats, 2625 1.23 christos ns_statscounter_recurshighwater, 2626 1.23 christos recurscount + 1); 2627 1.23 christos 2628 1.23 christos return result; 2629 1.23 christos } 2630 1.23 christos 2631 1.23 christos static isc_result_t 2632 1.23 christos recursionquotatype_attach_hard(ns_client_t *client) { 2633 1.23 christos return recursionquotatype_attach(client, false); 2634 1.23 christos } 2635 1.23 christos 2636 1.23 christos static isc_result_t 2637 1.23 christos recursionquotatype_attach_soft(ns_client_t *client) { 2638 1.23 christos return recursionquotatype_attach(client, true); 2639 1.23 christos } 2640 1.23 christos 2641 1.23 christos static void 2642 1.23 christos recursionquotatype_detach(ns_client_t *client) { 2643 1.23 christos isc_quota_release(&client->manager->sctx->recursionquota); 2644 1.23 christos ns_stats_decrement(client->manager->sctx->nsstats, 2645 1.23 christos ns_statscounter_recursclients); 2646 1.23 christos } 2647 1.23 christos 2648 1.23 christos static void 2649 1.23 christos stale_refresh_aftermath(ns_client_t *client, isc_result_t result) { 2650 1.23 christos dns_db_t *db = NULL; 2651 1.23 christos unsigned int dboptions; 2652 1.23 christos isc_buffer_t buffer; 2653 1.23 christos query_ctx_t qctx; 2654 1.23 christos dns_clientinfomethods_t cm; 2655 1.23 christos dns_clientinfo_t ci; 2656 1.23 christos char namebuf[DNS_NAME_FORMATSIZE]; 2657 1.23 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 2658 1.23 christos 2659 1.1 christos /* 2660 1.23 christos * If refreshing a stale RRset failed, we need to set the 2661 1.23 christos * stale-refresh-time window, so that on future requests for this 2662 1.23 christos * RRset the stale entry may be used immediately. 2663 1.1 christos */ 2664 1.23 christos switch (result) { 2665 1.23 christos case ISC_R_SUCCESS: 2666 1.23 christos case DNS_R_GLUE: 2667 1.23 christos case DNS_R_ZONECUT: 2668 1.23 christos case ISC_R_NOTFOUND: 2669 1.23 christos case DNS_R_DELEGATION: 2670 1.23 christos case DNS_R_EMPTYNAME: 2671 1.23 christos case DNS_R_NXRRSET: 2672 1.23 christos case DNS_R_EMPTYWILD: 2673 1.23 christos case DNS_R_NXDOMAIN: 2674 1.23 christos case DNS_R_COVERINGNSEC: 2675 1.23 christos case DNS_R_NCACHENXDOMAIN: 2676 1.23 christos case DNS_R_NCACHENXRRSET: 2677 1.23 christos case DNS_R_CNAME: 2678 1.23 christos case DNS_R_DNAME: 2679 1.23 christos break; 2680 1.23 christos default: 2681 1.23 christos dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); 2682 1.23 christos dns_rdatatype_format(client->query.qtype, typebuf, 2683 1.23 christos sizeof(typebuf)); 2684 1.23 christos ns_client_log(client, NS_LOGCATEGORY_SERVE_STALE, 2685 1.23 christos NS_LOGMODULE_QUERY, ISC_LOG_NOTICE, 2686 1.23 christos "%s/%s stale refresh failed: timed out", namebuf, 2687 1.23 christos typebuf); 2688 1.23 christos 2689 1.23 christos /* 2690 1.23 christos * Set up a short lived query context, solely to set the 2691 1.23 christos * last refresh failure time on the RRset in the cache 2692 1.23 christos * database, starting the stale-refresh-time window for it. 2693 1.23 christos * This is a condensed form of query_lookup(). 2694 1.23 christos */ 2695 1.23 christos client->now = isc_stdtime_now(); 2696 1.23 christos client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK; 2697 1.23 christos qctx_init(client, NULL, 0, &qctx); 2698 1.23 christos 2699 1.23 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 2700 1.23 christos dns_clientinfo_init(&ci, qctx.client, NULL); 2701 1.23 christos if (HAVEECS(qctx.client)) { 2702 1.23 christos dns_clientinfo_setecs(&ci, &qctx.client->ecs); 2703 1.23 christos } 2704 1.23 christos 2705 1.23 christos result = qctx_prepare_buffers(&qctx, &buffer); 2706 1.23 christos if (result != ISC_R_SUCCESS) { 2707 1.23 christos goto cleanup; 2708 1.23 christos } 2709 1.23 christos 2710 1.23 christos dboptions = qctx.client->query.dboptions; 2711 1.23 christos dboptions |= DNS_DBFIND_STALEOK; 2712 1.23 christos dboptions |= DNS_DBFIND_STALESTART; 2713 1.23 christos 2714 1.23 christos dns_db_attach(qctx.client->view->cachedb, &db); 2715 1.23 christos (void)dns_db_findext(db, qctx.client->query.qname, NULL, 2716 1.23 christos qctx.client->query.qtype, dboptions, 2717 1.23 christos qctx.client->now, &qctx.node, qctx.fname, 2718 1.23 christos &cm, &ci, qctx.rdataset, qctx.sigrdataset); 2719 1.23 christos if (qctx.node != NULL) { 2720 1.23 christos dns_db_detachnode(db, &qctx.node); 2721 1.23 christos } 2722 1.23 christos dns_db_detach(&db); 2723 1.23 christos 2724 1.23 christos cleanup: 2725 1.23 christos qctx_freedata(&qctx); 2726 1.23 christos qctx_destroy(&qctx); 2727 1.9 christos } 2728 1.1 christos } 2729 1.1 christos 2730 1.1 christos static void 2731 1.23 christos cleanup_after_fetch(dns_fetchresponse_t *resp, const char *ctracestr, 2732 1.23 christos ns_query_rectype_t recursion_type) { 2733 1.23 christos ns_client_t *client = resp->arg; 2734 1.23 christos isc_nmhandle_t **handlep = NULL; 2735 1.23 christos dns_fetch_t **fetchp = NULL; 2736 1.23 christos isc_result_t result; 2737 1.1 christos 2738 1.23 christos REQUIRE(NS_CLIENT_VALID(client)); 2739 1.1 christos 2740 1.23 christos CTRACE(ISC_LOG_DEBUG(3), ctracestr); 2741 1.1 christos 2742 1.23 christos handlep = &client->query.recursions[recursion_type].handle; 2743 1.23 christos fetchp = &client->query.recursions[recursion_type].fetch; 2744 1.23 christos result = resp->result; 2745 1.9 christos 2746 1.1 christos LOCK(&client->query.fetchlock); 2747 1.23 christos if (*fetchp != NULL) { 2748 1.23 christos INSIST(resp->fetch == *fetchp); 2749 1.23 christos *fetchp = NULL; 2750 1.1 christos } 2751 1.1 christos UNLOCK(&client->query.fetchlock); 2752 1.9 christos 2753 1.23 christos /* Some type of recursions require a bit of aftermath. */ 2754 1.23 christos if (recursion_type == RECTYPE_STALE_REFRESH) { 2755 1.23 christos stale_refresh_aftermath(client, result); 2756 1.9 christos } 2757 1.9 christos 2758 1.23 christos recursionquotatype_detach(client); 2759 1.23 christos free_fresp(client, &resp); 2760 1.23 christos isc_nmhandle_detach(handlep); 2761 1.23 christos } 2762 1.23 christos 2763 1.23 christos static void 2764 1.23 christos prefetch_done(void *arg) { 2765 1.23 christos cleanup_after_fetch(arg, "prefetch_done", RECTYPE_PREFETCH); 2766 1.1 christos } 2767 1.1 christos 2768 1.1 christos static void 2769 1.23 christos rpzfetch_done(void *arg) { 2770 1.23 christos cleanup_after_fetch(arg, "rpzfetch_done", RECTYPE_RPZ); 2771 1.23 christos } 2772 1.23 christos 2773 1.23 christos static void 2774 1.23 christos stale_refresh_done(void *arg) { 2775 1.23 christos cleanup_after_fetch(arg, "stale_refresh_done", RECTYPE_STALE_REFRESH); 2776 1.23 christos } 2777 1.23 christos 2778 1.23 christos /* 2779 1.23 christos * Try initiating a fetch for the given 'qname' and 'qtype' (using the slot in 2780 1.23 christos * the 'recursions' array indicated by 'recursion_type') that will be 2781 1.23 christos * associated with 'client'. If the recursive clients quota (or even soft 2782 1.23 christos * quota) is reached or some other error occurs, just return without starting 2783 1.23 christos * the fetch. If a fetch is successfully created, its results will be cached 2784 1.23 christos * upon successful completion, but no further actions will be taken afterwards. 2785 1.23 christos */ 2786 1.23 christos static void 2787 1.23 christos fetch_and_forget(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t qtype, 2788 1.23 christos ns_query_rectype_t recursion_type) { 2789 1.23 christos dns_rdataset_t *tmprdataset; 2790 1.1 christos isc_sockaddr_t *peeraddr; 2791 1.1 christos unsigned int options; 2792 1.23 christos isc_job_cb cb; 2793 1.23 christos isc_nmhandle_t **handlep; 2794 1.23 christos dns_fetch_t **fetchp; 2795 1.23 christos isc_result_t result; 2796 1.1 christos 2797 1.23 christos result = recursionquotatype_attach_hard(client); 2798 1.23 christos if (result != ISC_R_SUCCESS) { 2799 1.1 christos return; 2800 1.9 christos } 2801 1.1 christos 2802 1.3 christos tmprdataset = ns_client_newrdataset(client); 2803 1.9 christos 2804 1.9 christos if (!TCP(client)) { 2805 1.1 christos peeraddr = &client->peeraddr; 2806 1.9 christos } else { 2807 1.1 christos peeraddr = NULL; 2808 1.9 christos } 2809 1.9 christos 2810 1.23 christos switch (recursion_type) { 2811 1.23 christos case RECTYPE_PREFETCH: 2812 1.23 christos options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH; 2813 1.23 christos cb = prefetch_done; 2814 1.23 christos break; 2815 1.23 christos case RECTYPE_RPZ: 2816 1.23 christos options = client->query.fetchoptions; 2817 1.23 christos cb = rpzfetch_done; 2818 1.23 christos break; 2819 1.23 christos case RECTYPE_STALE_REFRESH: 2820 1.23 christos options = client->query.fetchoptions; 2821 1.23 christos cb = stale_refresh_done; 2822 1.23 christos break; 2823 1.23 christos default: 2824 1.23 christos UNREACHABLE(); 2825 1.23 christos } 2826 1.23 christos 2827 1.23 christos handlep = &client->query.recursions[recursion_type].handle; 2828 1.23 christos fetchp = &client->query.recursions[recursion_type].fetch; 2829 1.23 christos 2830 1.23 christos isc_nmhandle_attach(client->handle, handlep); 2831 1.9 christos result = dns_resolver_createfetch( 2832 1.23 christos client->view->resolver, qname, qtype, NULL, NULL, NULL, 2833 1.23 christos peeraddr, client->message->id, options, 0, NULL, 2834 1.26 christos client->query.qc, NULL, client->manager->loop, cb, client, NULL, 2835 1.24 christos tmprdataset, NULL, fetchp); 2836 1.1 christos if (result != ISC_R_SUCCESS) { 2837 1.3 christos ns_client_putrdataset(client, &tmprdataset); 2838 1.23 christos isc_nmhandle_detach(handlep); 2839 1.23 christos recursionquotatype_detach(client); 2840 1.1 christos } 2841 1.23 christos } 2842 1.23 christos 2843 1.23 christos static void 2844 1.26 christos query_stale_refresh(ns_client_t *client, dns_name_t *qname, 2845 1.26 christos dns_rdataset_t *rdataset) { 2846 1.26 christos CTRACE(ISC_LOG_DEBUG(3), "query_stale_refresh"); 2847 1.26 christos 2848 1.26 christos bool stale_refresh_window = false; 2849 1.26 christos bool stale_rrset = true; 2850 1.26 christos 2851 1.26 christos if (rdataset != NULL) { 2852 1.26 christos stale_refresh_window = (STALE_WINDOW(rdataset) && 2853 1.26 christos (client->query.dboptions & 2854 1.26 christos DNS_DBFIND_STALEENABLED) != 0); 2855 1.26 christos stale_rrset = STALE(rdataset); 2856 1.26 christos } 2857 1.26 christos 2858 1.26 christos if (FETCH_RECTYPE_STALE_REFRESH(client) != NULL || 2859 1.26 christos (client->query.dboptions & DNS_DBFIND_STALETIMEOUT) == 0 || 2860 1.26 christos !stale_rrset || stale_refresh_window) 2861 1.26 christos { 2862 1.26 christos return; 2863 1.26 christos } 2864 1.26 christos 2865 1.26 christos char namebuf[DNS_NAME_FORMATSIZE]; 2866 1.26 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 2867 1.26 christos dns_name_format(qname, namebuf, sizeof(namebuf)); 2868 1.26 christos dns_rdatatype_format(client->query.qtype, typebuf, sizeof(typebuf)); 2869 1.26 christos isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE, NS_LOGMODULE_QUERY, 2870 1.26 christos ISC_LOG_INFO, 2871 1.26 christos "%s %s stale answer used, an attempt " 2872 1.26 christos "to refresh the RRset will still be " 2873 1.26 christos "made", 2874 1.26 christos namebuf, typebuf); 2875 1.26 christos 2876 1.26 christos client->query.dboptions &= ~(DNS_DBFIND_STALETIMEOUT | 2877 1.26 christos DNS_DBFIND_STALEOK | 2878 1.26 christos DNS_DBFIND_STALEENABLED); 2879 1.26 christos 2880 1.26 christos fetch_and_forget(client, qname, client->query.qtype, 2881 1.26 christos RECTYPE_STALE_REFRESH); 2882 1.26 christos } 2883 1.26 christos 2884 1.26 christos static void 2885 1.26 christos query_stale_refresh_ncache(ns_client_t *client) { 2886 1.26 christos dns_name_t *qname; 2887 1.26 christos 2888 1.26 christos if (client->query.origqname != NULL) { 2889 1.26 christos qname = client->query.origqname; 2890 1.26 christos } else { 2891 1.26 christos qname = client->query.qname; 2892 1.26 christos } 2893 1.26 christos query_stale_refresh(client, qname, NULL); 2894 1.26 christos } 2895 1.26 christos 2896 1.26 christos static void 2897 1.23 christos query_prefetch(ns_client_t *client, dns_name_t *qname, 2898 1.23 christos dns_rdataset_t *rdataset) { 2899 1.23 christos CTRACE(ISC_LOG_DEBUG(3), "query_prefetch"); 2900 1.23 christos 2901 1.23 christos if (FETCH_RECTYPE_PREFETCH(client) != NULL || 2902 1.23 christos client->view->prefetch_trigger == 0U || 2903 1.23 christos rdataset->ttl > client->view->prefetch_trigger || 2904 1.23 christos (rdataset->attributes & DNS_RDATASETATTR_PREFETCH) == 0) 2905 1.23 christos { 2906 1.26 christos /* maybe refresh stale data */ 2907 1.26 christos query_stale_refresh(client, qname, rdataset); 2908 1.23 christos return; 2909 1.23 christos } 2910 1.23 christos 2911 1.23 christos fetch_and_forget(client, qname, rdataset->type, RECTYPE_PREFETCH); 2912 1.9 christos 2913 1.1 christos dns_rdataset_clearprefetch(rdataset); 2914 1.23 christos ns_stats_increment(client->manager->sctx->nsstats, 2915 1.23 christos ns_statscounter_prefetch); 2916 1.23 christos 2917 1.26 christos return; 2918 1.1 christos } 2919 1.1 christos 2920 1.15 christos static void 2921 1.1 christos rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep, 2922 1.9 christos dns_rdataset_t **rdatasetp) { 2923 1.1 christos if (nodep != NULL && *nodep != NULL) { 2924 1.1 christos REQUIRE(dbp != NULL && *dbp != NULL); 2925 1.1 christos dns_db_detachnode(*dbp, nodep); 2926 1.1 christos } 2927 1.9 christos if (dbp != NULL && *dbp != NULL) { 2928 1.1 christos dns_db_detach(dbp); 2929 1.9 christos } 2930 1.9 christos if (zonep != NULL && *zonep != NULL) { 2931 1.1 christos dns_zone_detach(zonep); 2932 1.9 christos } 2933 1.1 christos if (rdatasetp != NULL && *rdatasetp != NULL && 2934 1.1 christos dns_rdataset_isassociated(*rdatasetp)) 2935 1.9 christos { 2936 1.1 christos dns_rdataset_disassociate(*rdatasetp); 2937 1.9 christos } 2938 1.1 christos } 2939 1.1 christos 2940 1.15 christos static void 2941 1.1 christos rpz_match_clear(dns_rpz_st_t *st) { 2942 1.1 christos rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset); 2943 1.1 christos st->m.version = NULL; 2944 1.1 christos } 2945 1.1 christos 2946 1.15 christos static isc_result_t 2947 1.1 christos rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp) { 2948 1.1 christos REQUIRE(rdatasetp != NULL); 2949 1.1 christos 2950 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_ready"); 2951 1.1 christos 2952 1.1 christos if (*rdatasetp == NULL) { 2953 1.3 christos *rdatasetp = ns_client_newrdataset(client); 2954 1.1 christos } else if (dns_rdataset_isassociated(*rdatasetp)) { 2955 1.1 christos dns_rdataset_disassociate(*rdatasetp); 2956 1.1 christos } 2957 1.23 christos return ISC_R_SUCCESS; 2958 1.1 christos } 2959 1.1 christos 2960 1.1 christos static void 2961 1.1 christos rpz_st_clear(ns_client_t *client) { 2962 1.1 christos dns_rpz_st_t *st = client->query.rpz_st; 2963 1.1 christos 2964 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_st_clear"); 2965 1.1 christos 2966 1.1 christos if (st->m.rdataset != NULL) { 2967 1.3 christos ns_client_putrdataset(client, &st->m.rdataset); 2968 1.1 christos } 2969 1.1 christos rpz_match_clear(st); 2970 1.1 christos 2971 1.1 christos rpz_clean(NULL, &st->r.db, NULL, NULL); 2972 1.1 christos if (st->r.ns_rdataset != NULL) { 2973 1.3 christos ns_client_putrdataset(client, &st->r.ns_rdataset); 2974 1.1 christos } 2975 1.1 christos if (st->r.r_rdataset != NULL) { 2976 1.3 christos ns_client_putrdataset(client, &st->r.r_rdataset); 2977 1.1 christos } 2978 1.1 christos 2979 1.1 christos rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL); 2980 1.1 christos if (st->q.rdataset != NULL) { 2981 1.3 christos ns_client_putrdataset(client, &st->q.rdataset); 2982 1.1 christos } 2983 1.1 christos if (st->q.sigrdataset != NULL) { 2984 1.3 christos ns_client_putrdataset(client, &st->q.sigrdataset); 2985 1.1 christos } 2986 1.1 christos st->state = 0; 2987 1.1 christos st->m.type = DNS_RPZ_TYPE_BAD; 2988 1.1 christos st->m.policy = DNS_RPZ_POLICY_MISS; 2989 1.1 christos if (st->rpsdb != NULL) { 2990 1.1 christos dns_db_detach(&st->rpsdb); 2991 1.1 christos } 2992 1.1 christos } 2993 1.1 christos 2994 1.1 christos static dns_rpz_zbits_t 2995 1.9 christos rpz_get_zbits(ns_client_t *client, dns_rdatatype_t ip_type, 2996 1.9 christos dns_rpz_type_t rpz_type) { 2997 1.1 christos dns_rpz_st_t *st; 2998 1.3 christos dns_rpz_zbits_t zbits = 0; 2999 1.1 christos 3000 1.1 christos REQUIRE(client != NULL); 3001 1.1 christos REQUIRE(client->query.rpz_st != NULL); 3002 1.1 christos 3003 1.1 christos st = client->query.rpz_st; 3004 1.1 christos 3005 1.1 christos #ifdef USE_DNSRPS 3006 1.1 christos if (st->popt.dnsrps_enabled) { 3007 1.1 christos if (st->rpsdb == NULL || 3008 1.1 christos librpz->have_trig(dns_dnsrps_type2trig(rpz_type), 3009 1.1 christos ip_type == dns_rdatatype_aaaa, 3010 1.23 christos ((dns_rpsdb_t *)st->rpsdb)->rsp)) 3011 1.1 christos { 3012 1.23 christos return DNS_RPZ_ALL_ZBITS; 3013 1.1 christos } 3014 1.23 christos return 0; 3015 1.1 christos } 3016 1.9 christos #endif /* ifdef USE_DNSRPS */ 3017 1.1 christos 3018 1.1 christos switch (rpz_type) { 3019 1.1 christos case DNS_RPZ_TYPE_CLIENT_IP: 3020 1.1 christos zbits = st->have.client_ip; 3021 1.1 christos break; 3022 1.1 christos case DNS_RPZ_TYPE_QNAME: 3023 1.1 christos zbits = st->have.qname; 3024 1.1 christos break; 3025 1.1 christos case DNS_RPZ_TYPE_IP: 3026 1.1 christos if (ip_type == dns_rdatatype_a) { 3027 1.1 christos zbits = st->have.ipv4; 3028 1.1 christos } else if (ip_type == dns_rdatatype_aaaa) { 3029 1.1 christos zbits = st->have.ipv6; 3030 1.1 christos } else { 3031 1.1 christos zbits = st->have.ip; 3032 1.1 christos } 3033 1.1 christos break; 3034 1.1 christos case DNS_RPZ_TYPE_NSDNAME: 3035 1.1 christos zbits = st->have.nsdname; 3036 1.1 christos break; 3037 1.1 christos case DNS_RPZ_TYPE_NSIP: 3038 1.1 christos if (ip_type == dns_rdatatype_a) { 3039 1.1 christos zbits = st->have.nsipv4; 3040 1.1 christos } else if (ip_type == dns_rdatatype_aaaa) { 3041 1.1 christos zbits = st->have.nsipv6; 3042 1.1 christos } else { 3043 1.1 christos zbits = st->have.nsip; 3044 1.1 christos } 3045 1.1 christos break; 3046 1.1 christos default: 3047 1.15 christos UNREACHABLE(); 3048 1.1 christos } 3049 1.1 christos 3050 1.1 christos /* 3051 1.1 christos * Choose 3052 1.1 christos * the earliest configured policy zone (rpz->num) 3053 1.1 christos * QNAME over IP over NSDNAME over NSIP (rpz_type) 3054 1.1 christos * the smallest name, 3055 1.1 christos * the longest IP address prefix, 3056 1.1 christos * the lexically smallest address. 3057 1.1 christos */ 3058 1.1 christos if (st->m.policy != DNS_RPZ_POLICY_MISS) { 3059 1.1 christos if (st->m.type >= rpz_type) { 3060 1.1 christos zbits &= DNS_RPZ_ZMASK(st->m.rpz->num); 3061 1.9 christos } else { 3062 1.1 christos zbits &= DNS_RPZ_ZMASK(st->m.rpz->num) >> 1; 3063 1.1 christos } 3064 1.1 christos } 3065 1.1 christos 3066 1.1 christos /* 3067 1.1 christos * If the client wants recursion, allow only compatible policies. 3068 1.1 christos */ 3069 1.9 christos if (!RECURSIONOK(client)) { 3070 1.1 christos zbits &= st->popt.no_rd_ok; 3071 1.9 christos } 3072 1.1 christos 3073 1.23 christos return zbits; 3074 1.1 christos } 3075 1.1 christos 3076 1.1 christos static void 3077 1.1 christos query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) { 3078 1.9 christos CTRACE(ISC_LOG_DEBUG(3), "query_rpzfetch"); 3079 1.9 christos 3080 1.23 christos if (FETCH_RECTYPE_RPZ(client) != NULL) { 3081 1.1 christos return; 3082 1.9 christos } 3083 1.9 christos 3084 1.23 christos fetch_and_forget(client, qname, type, RECTYPE_RPZ); 3085 1.1 christos } 3086 1.1 christos 3087 1.1 christos /* 3088 1.1 christos * Get an NS, A, or AAAA rrset related to the response for the client 3089 1.1 christos * to check the contents of that rrset for hits by eligible policy zones. 3090 1.1 christos */ 3091 1.1 christos static isc_result_t 3092 1.1 christos rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, 3093 1.15 christos unsigned int options, dns_rpz_type_t rpz_type, dns_db_t **dbp, 3094 1.1 christos dns_dbversion_t *version, dns_rdataset_t **rdatasetp, 3095 1.9 christos bool resuming) { 3096 1.1 christos dns_rpz_st_t *st; 3097 1.3 christos bool is_zone; 3098 1.1 christos dns_dbnode_t *node; 3099 1.1 christos dns_fixedname_t fixed; 3100 1.1 christos dns_name_t *found; 3101 1.1 christos isc_result_t result; 3102 1.1 christos dns_clientinfomethods_t cm; 3103 1.1 christos dns_clientinfo_t ci; 3104 1.1 christos 3105 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rrset_find"); 3106 1.1 christos 3107 1.1 christos st = client->query.rpz_st; 3108 1.1 christos if ((st->state & DNS_RPZ_RECURSING) != 0) { 3109 1.1 christos INSIST(st->r.r_type == type); 3110 1.1 christos INSIST(dns_name_equal(name, st->r_name)); 3111 1.1 christos INSIST(*rdatasetp == NULL || 3112 1.1 christos !dns_rdataset_isassociated(*rdatasetp)); 3113 1.1 christos st->state &= ~DNS_RPZ_RECURSING; 3114 1.1 christos RESTORE(*dbp, st->r.db); 3115 1.3 christos if (*rdatasetp != NULL) { 3116 1.3 christos ns_client_putrdataset(client, rdatasetp); 3117 1.3 christos } 3118 1.1 christos RESTORE(*rdatasetp, st->r.r_rdataset); 3119 1.1 christos result = st->r.r_result; 3120 1.1 christos if (result == DNS_R_DELEGATION) { 3121 1.1 christos CTRACE(ISC_LOG_ERROR, "RPZ recursing"); 3122 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, 3123 1.3 christos rpz_type, "rpz_rrset_find(1)", result); 3124 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 3125 1.1 christos result = DNS_R_SERVFAIL; 3126 1.1 christos } 3127 1.23 christos return result; 3128 1.1 christos } 3129 1.1 christos 3130 1.1 christos result = rpz_ready(client, rdatasetp); 3131 1.1 christos if (result != ISC_R_SUCCESS) { 3132 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 3133 1.23 christos return result; 3134 1.1 christos } 3135 1.1 christos if (*dbp != NULL) { 3136 1.3 christos is_zone = false; 3137 1.1 christos } else { 3138 1.1 christos dns_zone_t *zone; 3139 1.1 christos 3140 1.1 christos version = NULL; 3141 1.1 christos zone = NULL; 3142 1.23 christos result = query_getdb(client, name, type, 3143 1.23 christos (dns_getdb_options_t){ 0 }, &zone, dbp, 3144 1.1 christos &version, &is_zone); 3145 1.1 christos if (result != ISC_R_SUCCESS) { 3146 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, 3147 1.3 christos rpz_type, "rpz_rrset_find(2)", result); 3148 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 3149 1.9 christos if (zone != NULL) { 3150 1.1 christos dns_zone_detach(&zone); 3151 1.9 christos } 3152 1.23 christos return result; 3153 1.1 christos } 3154 1.9 christos if (zone != NULL) { 3155 1.1 christos dns_zone_detach(&zone); 3156 1.9 christos } 3157 1.1 christos } 3158 1.1 christos 3159 1.1 christos node = NULL; 3160 1.1 christos found = dns_fixedname_initname(&fixed); 3161 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 3162 1.20 christos dns_clientinfo_init(&ci, client, NULL); 3163 1.15 christos result = dns_db_findext(*dbp, name, version, type, options, client->now, 3164 1.15 christos &node, found, &cm, &ci, *rdatasetp, NULL); 3165 1.1 christos if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) { 3166 1.1 christos /* 3167 1.1 christos * Try the cache if we're authoritative for an 3168 1.1 christos * ancestor but not the domain itself. 3169 1.1 christos */ 3170 1.1 christos rpz_clean(NULL, dbp, &node, rdatasetp); 3171 1.1 christos version = NULL; 3172 1.1 christos dns_db_attach(client->view->cachedb, dbp); 3173 1.9 christos result = dns_db_findext(*dbp, name, version, type, 0, 3174 1.9 christos client->now, &node, found, &cm, &ci, 3175 1.9 christos *rdatasetp, NULL); 3176 1.1 christos } 3177 1.1 christos rpz_clean(NULL, dbp, &node, NULL); 3178 1.1 christos if (result == DNS_R_DELEGATION) { 3179 1.1 christos rpz_clean(NULL, NULL, NULL, rdatasetp); 3180 1.1 christos /* 3181 1.1 christos * Recurse for NS rrset or A or AAAA rrset for an NS. 3182 1.1 christos * Do not recurse for addresses for the query name. 3183 1.1 christos */ 3184 1.1 christos if (rpz_type == DNS_RPZ_TYPE_IP) { 3185 1.1 christos result = DNS_R_NXRRSET; 3186 1.20 christos } else if (!client->view->rpzs->p.nsip_wait_recurse || 3187 1.20 christos (!client->view->rpzs->p.nsdname_wait_recurse && 3188 1.20 christos rpz_type == DNS_RPZ_TYPE_NSDNAME)) 3189 1.20 christos { 3190 1.1 christos query_rpzfetch(client, name, type); 3191 1.1 christos result = DNS_R_NXRRSET; 3192 1.1 christos } else { 3193 1.20 christos dns_name_copy(name, st->r_name); 3194 1.3 christos result = ns_query_recurse(client, type, st->r_name, 3195 1.3 christos NULL, NULL, resuming); 3196 1.1 christos if (result == ISC_R_SUCCESS) { 3197 1.1 christos st->state |= DNS_RPZ_RECURSING; 3198 1.1 christos result = DNS_R_DELEGATION; 3199 1.1 christos } 3200 1.1 christos } 3201 1.1 christos } 3202 1.23 christos return result; 3203 1.1 christos } 3204 1.1 christos 3205 1.1 christos /* 3206 1.1 christos * Compute a policy owner name, p_name, in a policy zone given the needed 3207 1.1 christos * policy type and the trigger name. 3208 1.1 christos */ 3209 1.1 christos static isc_result_t 3210 1.9 christos rpz_get_p_name(ns_client_t *client, dns_name_t *p_name, dns_rpz_zone_t *rpz, 3211 1.9 christos dns_rpz_type_t rpz_type, dns_name_t *trig_name) { 3212 1.1 christos dns_offsets_t prefix_offsets; 3213 1.1 christos dns_name_t prefix, *suffix; 3214 1.1 christos unsigned int first, labels; 3215 1.1 christos isc_result_t result; 3216 1.1 christos 3217 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_get_p_name"); 3218 1.1 christos 3219 1.1 christos /* 3220 1.1 christos * The policy owner name consists of a suffix depending on the type 3221 1.1 christos * and policy zone and a prefix that is the longest possible string 3222 1.1 christos * from the trigger name that keesp the resulting policy owner name 3223 1.1 christos * from being too long. 3224 1.1 christos */ 3225 1.1 christos switch (rpz_type) { 3226 1.1 christos case DNS_RPZ_TYPE_CLIENT_IP: 3227 1.1 christos suffix = &rpz->client_ip; 3228 1.1 christos break; 3229 1.1 christos case DNS_RPZ_TYPE_QNAME: 3230 1.1 christos suffix = &rpz->origin; 3231 1.1 christos break; 3232 1.1 christos case DNS_RPZ_TYPE_IP: 3233 1.1 christos suffix = &rpz->ip; 3234 1.1 christos break; 3235 1.1 christos case DNS_RPZ_TYPE_NSDNAME: 3236 1.1 christos suffix = &rpz->nsdname; 3237 1.1 christos break; 3238 1.1 christos case DNS_RPZ_TYPE_NSIP: 3239 1.1 christos suffix = &rpz->nsip; 3240 1.1 christos break; 3241 1.1 christos default: 3242 1.15 christos UNREACHABLE(); 3243 1.1 christos } 3244 1.1 christos 3245 1.1 christos /* 3246 1.1 christos * Start with relative version of the full trigger name, 3247 1.1 christos * and trim enough allow the addition of the suffix. 3248 1.1 christos */ 3249 1.1 christos dns_name_init(&prefix, prefix_offsets); 3250 1.1 christos labels = dns_name_countlabels(trig_name); 3251 1.1 christos first = 0; 3252 1.1 christos for (;;) { 3253 1.9 christos dns_name_getlabelsequence(trig_name, first, labels - first - 1, 3254 1.1 christos &prefix); 3255 1.1 christos result = dns_name_concatenate(&prefix, suffix, p_name, NULL); 3256 1.9 christos if (result == ISC_R_SUCCESS) { 3257 1.1 christos break; 3258 1.9 christos } 3259 1.1 christos INSIST(result == DNS_R_NAMETOOLONG); 3260 1.1 christos /* 3261 1.1 christos * Trim the trigger name until the combination is not too long. 3262 1.1 christos */ 3263 1.9 christos if (labels - first < 2) { 3264 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, suffix, 3265 1.9 christos rpz_type, "concatenate()", result); 3266 1.23 christos return ISC_R_FAILURE; 3267 1.1 christos } 3268 1.1 christos /* 3269 1.1 christos * Complain once about trimming the trigger name. 3270 1.1 christos */ 3271 1.1 christos if (first == 0) { 3272 1.1 christos rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, suffix, 3273 1.9 christos rpz_type, "concatenate()", result); 3274 1.1 christos } 3275 1.1 christos ++first; 3276 1.1 christos } 3277 1.23 christos return ISC_R_SUCCESS; 3278 1.1 christos } 3279 1.1 christos 3280 1.1 christos /* 3281 1.1 christos * Look in policy zone rpz for a policy of rpz_type by p_name. 3282 1.1 christos * The self-name (usually the client qname or an NS name) is compared with 3283 1.1 christos * the target of a CNAME policy for the old style passthru encoding. 3284 1.1 christos * If found, the policy is recorded in *zonep, *dbp, *versionp, *nodep, 3285 1.1 christos * *rdatasetp, and *policyp. 3286 1.1 christos * The target DNS type, qtype, chooses the best rdataset for *rdatasetp. 3287 1.1 christos * The caller must decide if the found policy is most suitable, including 3288 1.1 christos * better than a previously found policy. 3289 1.1 christos * If it is best, the caller records it in client->query.rpz_st->m. 3290 1.1 christos */ 3291 1.1 christos static isc_result_t 3292 1.1 christos rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype, 3293 1.1 christos dns_name_t *p_name, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, 3294 1.1 christos dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp, 3295 1.1 christos dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, 3296 1.9 christos dns_rpz_policy_t *policyp) { 3297 1.1 christos dns_fixedname_t foundf; 3298 1.1 christos dns_name_t *found; 3299 1.1 christos isc_result_t result; 3300 1.1 christos dns_clientinfomethods_t cm; 3301 1.1 christos dns_clientinfo_t ci; 3302 1.6 christos bool found_a = false; 3303 1.1 christos 3304 1.1 christos REQUIRE(nodep != NULL); 3305 1.1 christos 3306 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_find_p"); 3307 1.1 christos 3308 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 3309 1.20 christos dns_clientinfo_init(&ci, client, NULL); 3310 1.1 christos 3311 1.1 christos /* 3312 1.1 christos * Try to find either a CNAME or the type of record demanded by the 3313 1.1 christos * request from the policy zone. 3314 1.1 christos */ 3315 1.1 christos rpz_clean(zonep, dbp, nodep, rdatasetp); 3316 1.1 christos result = rpz_ready(client, rdatasetp); 3317 1.1 christos if (result != ISC_R_SUCCESS) { 3318 1.1 christos CTRACE(ISC_LOG_ERROR, "rpz_ready() failed"); 3319 1.23 christos return DNS_R_SERVFAIL; 3320 1.1 christos } 3321 1.1 christos *versionp = NULL; 3322 1.1 christos result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp); 3323 1.9 christos if (result != ISC_R_SUCCESS) { 3324 1.23 christos return DNS_R_NXDOMAIN; 3325 1.9 christos } 3326 1.1 christos found = dns_fixedname_initname(&foundf); 3327 1.1 christos 3328 1.1 christos result = dns_db_findext(*dbp, p_name, *versionp, dns_rdatatype_any, 0, 3329 1.9 christos client->now, nodep, found, &cm, &ci, *rdatasetp, 3330 1.9 christos NULL); 3331 1.1 christos /* 3332 1.1 christos * Choose the best rdataset if we found something. 3333 1.1 christos */ 3334 1.1 christos if (result == ISC_R_SUCCESS) { 3335 1.1 christos dns_rdatasetiter_t *rdsiter; 3336 1.1 christos 3337 1.1 christos rdsiter = NULL; 3338 1.16 christos result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0, 0, 3339 1.1 christos &rdsiter); 3340 1.1 christos if (result != ISC_R_SUCCESS) { 3341 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, 3342 1.3 christos rpz_type, "allrdatasets()", result); 3343 1.1 christos CTRACE(ISC_LOG_ERROR, 3344 1.1 christos "rpz_find_p: allrdatasets failed"); 3345 1.23 christos return DNS_R_SERVFAIL; 3346 1.1 christos } 3347 1.6 christos if (qtype == dns_rdatatype_aaaa && 3348 1.16 christos !ISC_LIST_EMPTY(client->view->dns64)) 3349 1.16 christos { 3350 1.6 christos for (result = dns_rdatasetiter_first(rdsiter); 3351 1.6 christos result == ISC_R_SUCCESS; 3352 1.9 christos result = dns_rdatasetiter_next(rdsiter)) 3353 1.9 christos { 3354 1.6 christos dns_rdatasetiter_current(rdsiter, *rdatasetp); 3355 1.6 christos if ((*rdatasetp)->type == dns_rdatatype_a) { 3356 1.6 christos found_a = true; 3357 1.6 christos } 3358 1.6 christos dns_rdataset_disassociate(*rdatasetp); 3359 1.6 christos } 3360 1.6 christos } 3361 1.1 christos for (result = dns_rdatasetiter_first(rdsiter); 3362 1.1 christos result == ISC_R_SUCCESS; 3363 1.9 christos result = dns_rdatasetiter_next(rdsiter)) 3364 1.9 christos { 3365 1.1 christos dns_rdatasetiter_current(rdsiter, *rdatasetp); 3366 1.1 christos if ((*rdatasetp)->type == dns_rdatatype_cname || 3367 1.16 christos (*rdatasetp)->type == qtype) 3368 1.16 christos { 3369 1.1 christos break; 3370 1.9 christos } 3371 1.1 christos dns_rdataset_disassociate(*rdatasetp); 3372 1.1 christos } 3373 1.1 christos dns_rdatasetiter_destroy(&rdsiter); 3374 1.1 christos if (result != ISC_R_SUCCESS) { 3375 1.1 christos if (result != ISC_R_NOMORE) { 3376 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, 3377 1.9 christos p_name, rpz_type, "rdatasetiter", 3378 1.9 christos result); 3379 1.9 christos CTRACE(ISC_LOG_ERROR, "rpz_find_p: " 3380 1.9 christos "rdatasetiter failed"); 3381 1.23 christos return DNS_R_SERVFAIL; 3382 1.1 christos } 3383 1.1 christos /* 3384 1.1 christos * Ask again to get the right DNS_R_DNAME/NXRRSET/... 3385 1.1 christos * result if there is neither a CNAME nor target type. 3386 1.1 christos */ 3387 1.9 christos if (dns_rdataset_isassociated(*rdatasetp)) { 3388 1.1 christos dns_rdataset_disassociate(*rdatasetp); 3389 1.9 christos } 3390 1.1 christos dns_db_detachnode(*dbp, nodep); 3391 1.1 christos 3392 1.1 christos if (qtype == dns_rdatatype_rrsig || 3393 1.16 christos qtype == dns_rdatatype_sig) 3394 1.16 christos { 3395 1.1 christos result = DNS_R_NXRRSET; 3396 1.9 christos } else { 3397 1.1 christos result = dns_db_findext(*dbp, p_name, *versionp, 3398 1.1 christos qtype, 0, client->now, 3399 1.1 christos nodep, found, &cm, &ci, 3400 1.1 christos *rdatasetp, NULL); 3401 1.9 christos } 3402 1.1 christos } 3403 1.1 christos } 3404 1.1 christos switch (result) { 3405 1.1 christos case ISC_R_SUCCESS: 3406 1.1 christos if ((*rdatasetp)->type != dns_rdatatype_cname) { 3407 1.1 christos *policyp = DNS_RPZ_POLICY_RECORD; 3408 1.1 christos } else { 3409 1.1 christos *policyp = dns_rpz_decode_cname(rpz, *rdatasetp, 3410 1.1 christos self_name); 3411 1.1 christos if ((*policyp == DNS_RPZ_POLICY_RECORD || 3412 1.1 christos *policyp == DNS_RPZ_POLICY_WILDCNAME) && 3413 1.1 christos qtype != dns_rdatatype_cname && 3414 1.1 christos qtype != dns_rdatatype_any) 3415 1.9 christos { 3416 1.23 christos return DNS_R_CNAME; 3417 1.9 christos } 3418 1.1 christos } 3419 1.23 christos return ISC_R_SUCCESS; 3420 1.1 christos case DNS_R_NXRRSET: 3421 1.6 christos if (found_a) { 3422 1.6 christos *policyp = DNS_RPZ_POLICY_DNS64; 3423 1.6 christos } else { 3424 1.6 christos *policyp = DNS_RPZ_POLICY_NODATA; 3425 1.6 christos } 3426 1.23 christos return result; 3427 1.1 christos case DNS_R_DNAME: 3428 1.9 christos /* 3429 1.9 christos * DNAME policy RRs have very few if any uses that are not 3430 1.9 christos * better served with simple wildcards. Making them work would 3431 1.9 christos * require complications to get the number of labels matched 3432 1.9 christos * in the name or the found name to the main DNS_R_DNAME case 3433 1.9 christos * in query_dname(). The domain also does not appear in the 3434 1.9 christos * summary database at the right level, so this happens only 3435 1.9 christos * with a single policy zone when we have no summary database. 3436 1.9 christos * Treat it as a miss. 3437 1.9 christos */ 3438 1.1 christos case DNS_R_NXDOMAIN: 3439 1.1 christos case DNS_R_EMPTYNAME: 3440 1.23 christos return DNS_R_NXDOMAIN; 3441 1.1 christos default: 3442 1.9 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, "", 3443 1.9 christos result); 3444 1.9 christos CTRACE(ISC_LOG_ERROR, "rpz_find_p: unexpected result"); 3445 1.23 christos return DNS_R_SERVFAIL; 3446 1.1 christos } 3447 1.1 christos } 3448 1.1 christos 3449 1.1 christos static void 3450 1.1 christos rpz_save_p(dns_rpz_st_t *st, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, 3451 1.1 christos dns_rpz_policy_t policy, dns_name_t *p_name, dns_rpz_prefix_t prefix, 3452 1.1 christos isc_result_t result, dns_zone_t **zonep, dns_db_t **dbp, 3453 1.1 christos dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, 3454 1.9 christos dns_dbversion_t *version) { 3455 1.1 christos dns_rdataset_t *trdataset = NULL; 3456 1.1 christos 3457 1.1 christos rpz_match_clear(st); 3458 1.1 christos st->m.rpz = rpz; 3459 1.1 christos st->m.type = rpz_type; 3460 1.1 christos st->m.policy = policy; 3461 1.20 christos dns_name_copy(p_name, st->p_name); 3462 1.1 christos st->m.prefix = prefix; 3463 1.1 christos st->m.result = result; 3464 1.1 christos SAVE(st->m.zone, *zonep); 3465 1.1 christos SAVE(st->m.db, *dbp); 3466 1.1 christos SAVE(st->m.node, *nodep); 3467 1.1 christos if (*rdatasetp != NULL && dns_rdataset_isassociated(*rdatasetp)) { 3468 1.1 christos /* 3469 1.1 christos * Save the replacement rdataset from the policy 3470 1.1 christos * and make the previous replacement rdataset scratch. 3471 1.1 christos */ 3472 1.1 christos SAVE(trdataset, st->m.rdataset); 3473 1.1 christos SAVE(st->m.rdataset, *rdatasetp); 3474 1.1 christos SAVE(*rdatasetp, trdataset); 3475 1.1 christos st->m.ttl = ISC_MIN(st->m.rdataset->ttl, rpz->max_policy_ttl); 3476 1.1 christos } else { 3477 1.1 christos st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT, rpz->max_policy_ttl); 3478 1.1 christos } 3479 1.1 christos SAVE(st->m.version, version); 3480 1.1 christos } 3481 1.1 christos 3482 1.1 christos #ifdef USE_DNSRPS 3483 1.1 christos /* 3484 1.1 christos * Check the results of a RPZ service interface lookup. 3485 1.1 christos * Stop after an error (<0) or not a hit on a disabled zone (0). 3486 1.1 christos * Continue after a hit on a disabled zone (>0). 3487 1.1 christos */ 3488 1.1 christos static int 3489 1.23 christos dnsrps_ck(librpz_emsg_t *emsg, ns_client_t *client, dns_rpsdb_t *rpsdb, 3490 1.9 christos bool recursed) { 3491 1.1 christos isc_region_t region; 3492 1.1 christos librpz_domain_buf_t pname_buf; 3493 1.1 christos 3494 1.23 christos CTRACE(ISC_LOG_DEBUG(3), "dnsrps_ck"); 3495 1.23 christos 3496 1.1 christos if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) { 3497 1.23 christos return -1; 3498 1.1 christos } 3499 1.1 christos 3500 1.1 christos /* 3501 1.1 christos * Forget the state from before the IP address or domain check 3502 1.1 christos * if the lookup hit nothing. 3503 1.1 christos */ 3504 1.1 christos if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED || 3505 1.1 christos rpsdb->result.hit_id != rpsdb->hit_id || 3506 1.1 christos rpsdb->result.policy != LIBRPZ_POLICY_DISABLED) 3507 1.1 christos { 3508 1.1 christos if (!librpz->rsp_pop_discard(emsg, rpsdb->rsp)) { 3509 1.23 christos return -1; 3510 1.1 christos } 3511 1.23 christos return 0; 3512 1.1 christos } 3513 1.1 christos 3514 1.1 christos /* 3515 1.1 christos * Log a hit on a disabled zone. 3516 1.1 christos * Forget the zone to not try it again, and restore the pre-hit state. 3517 1.1 christos */ 3518 1.1 christos if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) { 3519 1.23 christos return -1; 3520 1.1 christos } 3521 1.1 christos region.base = pname_buf.d; 3522 1.1 christos region.length = pname_buf.size; 3523 1.1 christos dns_name_fromregion(client->query.rpz_st->p_name, ®ion); 3524 1.9 christos rpz_log_rewrite(client, true, dns_dnsrps_2policy(rpsdb->result.zpolicy), 3525 1.1 christos dns_dnsrps_trig2type(rpsdb->result.trig), NULL, 3526 1.1 christos client->query.rpz_st->p_name, NULL, 3527 1.1 christos rpsdb->result.cznum); 3528 1.1 christos 3529 1.1 christos if (!librpz->rsp_forget_zone(emsg, rpsdb->result.cznum, rpsdb->rsp) || 3530 1.1 christos !librpz->rsp_pop(emsg, &rpsdb->result, rpsdb->rsp)) 3531 1.1 christos { 3532 1.23 christos return -1; 3533 1.1 christos } 3534 1.23 christos return 1; 3535 1.1 christos } 3536 1.1 christos 3537 1.1 christos /* 3538 1.1 christos * Ready the shim database and rdataset for a DNSRPS hit. 3539 1.1 christos */ 3540 1.3 christos static bool 3541 1.1 christos dnsrps_set_p(librpz_emsg_t *emsg, ns_client_t *client, dns_rpz_st_t *st, 3542 1.1 christos dns_rdatatype_t qtype, dns_rdataset_t **p_rdatasetp, 3543 1.9 christos bool recursed) { 3544 1.23 christos dns_rpsdb_t *rpsdb = NULL; 3545 1.1 christos librpz_domain_buf_t pname_buf; 3546 1.1 christos isc_region_t region; 3547 1.23 christos dns_zone_t *p_zone = NULL; 3548 1.23 christos dns_db_t *p_db = NULL; 3549 1.23 christos dns_dbnode_t *p_node = NULL; 3550 1.1 christos dns_rpz_policy_t policy; 3551 1.1 christos dns_rdatatype_t foundtype, searchtype; 3552 1.1 christos isc_result_t result; 3553 1.1 christos 3554 1.23 christos CTRACE(ISC_LOG_DEBUG(3), "dnsrps_set_p"); 3555 1.23 christos 3556 1.23 christos rpsdb = (dns_rpsdb_t *)st->rpsdb; 3557 1.1 christos 3558 1.1 christos if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) { 3559 1.23 christos return false; 3560 1.1 christos } 3561 1.1 christos 3562 1.1 christos if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED) { 3563 1.23 christos return true; 3564 1.1 christos } 3565 1.1 christos 3566 1.1 christos /* 3567 1.1 christos * Give the fake or shim DNSRPS database its new origin. 3568 1.1 christos */ 3569 1.1 christos if (!librpz->rsp_soa(emsg, NULL, NULL, &rpsdb->origin_buf, 3570 1.1 christos &rpsdb->result, rpsdb->rsp)) 3571 1.1 christos { 3572 1.23 christos return false; 3573 1.1 christos } 3574 1.1 christos region.base = rpsdb->origin_buf.d; 3575 1.1 christos region.length = rpsdb->origin_buf.size; 3576 1.1 christos dns_name_fromregion(&rpsdb->common.origin, ®ion); 3577 1.1 christos 3578 1.1 christos if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) { 3579 1.23 christos return false; 3580 1.1 christos } 3581 1.1 christos region.base = pname_buf.d; 3582 1.1 christos region.length = pname_buf.size; 3583 1.1 christos dns_name_fromregion(st->p_name, ®ion); 3584 1.1 christos 3585 1.23 christos result = rpz_ready(client, p_rdatasetp); 3586 1.23 christos if (result != ISC_R_SUCCESS) { 3587 1.23 christos return false; 3588 1.23 christos } 3589 1.1 christos dns_db_attach(st->rpsdb, &p_db); 3590 1.1 christos policy = dns_dnsrps_2policy(rpsdb->result.policy); 3591 1.1 christos if (policy != DNS_RPZ_POLICY_RECORD) { 3592 1.1 christos result = ISC_R_SUCCESS; 3593 1.1 christos } else if (qtype == dns_rdatatype_rrsig) { 3594 1.1 christos /* 3595 1.1 christos * dns_find_db() refuses to look for and fail to 3596 1.1 christos * find dns_rdatatype_rrsig. 3597 1.1 christos */ 3598 1.1 christos result = DNS_R_NXRRSET; 3599 1.1 christos policy = DNS_RPZ_POLICY_NODATA; 3600 1.1 christos } else { 3601 1.23 christos dns_fixedname_t foundf; 3602 1.23 christos dns_name_t *found = NULL; 3603 1.23 christos 3604 1.1 christos /* 3605 1.1 christos * Get the next (and so first) RR from the policy node. 3606 1.1 christos * If it is a CNAME, then look for it regardless of the 3607 1.1 christos * query type. 3608 1.1 christos */ 3609 1.1 christos if (!librpz->rsp_rr(emsg, &foundtype, NULL, NULL, NULL, 3610 1.1 christos &rpsdb->result, rpsdb->qname->ndata, 3611 1.1 christos rpsdb->qname->length, rpsdb->rsp)) 3612 1.1 christos { 3613 1.23 christos return false; 3614 1.1 christos } 3615 1.23 christos 3616 1.1 christos if (foundtype == dns_rdatatype_cname) { 3617 1.1 christos searchtype = dns_rdatatype_cname; 3618 1.1 christos } else { 3619 1.1 christos searchtype = qtype; 3620 1.1 christos } 3621 1.1 christos /* 3622 1.1 christos * Get the DNSPRS imitation rdataset. 3623 1.1 christos */ 3624 1.1 christos found = dns_fixedname_initname(&foundf); 3625 1.9 christos result = dns_db_find(p_db, st->p_name, NULL, searchtype, 0, 0, 3626 1.9 christos &p_node, found, *p_rdatasetp, NULL); 3627 1.1 christos 3628 1.1 christos if (result == ISC_R_SUCCESS) { 3629 1.1 christos if (searchtype == dns_rdatatype_cname && 3630 1.16 christos qtype != dns_rdatatype_cname) 3631 1.16 christos { 3632 1.1 christos result = DNS_R_CNAME; 3633 1.1 christos } 3634 1.1 christos } else if (result == DNS_R_NXRRSET) { 3635 1.1 christos policy = DNS_RPZ_POLICY_NODATA; 3636 1.1 christos } else { 3637 1.1 christos snprintf(emsg->c, sizeof(emsg->c), "dns_db_find(): %s", 3638 1.1 christos isc_result_totext(result)); 3639 1.23 christos return false; 3640 1.1 christos } 3641 1.1 christos } 3642 1.1 christos 3643 1.1 christos rpz_save_p(st, client->view->rpzs->zones[rpsdb->result.cznum], 3644 1.9 christos dns_dnsrps_trig2type(rpsdb->result.trig), policy, st->p_name, 3645 1.9 christos 0, result, &p_zone, &p_db, &p_node, p_rdatasetp, NULL); 3646 1.1 christos 3647 1.1 christos rpz_clean(NULL, NULL, NULL, p_rdatasetp); 3648 1.1 christos 3649 1.23 christos return true; 3650 1.1 christos } 3651 1.1 christos 3652 1.1 christos static isc_result_t 3653 1.1 christos dnsrps_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr, 3654 1.9 christos dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp) { 3655 1.1 christos dns_rpz_st_t *st; 3656 1.23 christos dns_rpsdb_t *rpsdb; 3657 1.1 christos librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP; 3658 1.3 christos bool recursed = false; 3659 1.1 christos int res; 3660 1.1 christos librpz_emsg_t emsg; 3661 1.1 christos isc_result_t result; 3662 1.1 christos 3663 1.23 christos CTRACE(ISC_LOG_DEBUG(3), "dnsrps_rewrite_ip"); 3664 1.23 christos 3665 1.1 christos st = client->query.rpz_st; 3666 1.23 christos rpsdb = (dns_rpsdb_t *)st->rpsdb; 3667 1.1 christos 3668 1.1 christos result = rpz_ready(client, p_rdatasetp); 3669 1.1 christos if (result != ISC_R_SUCCESS) { 3670 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 3671 1.23 christos return result; 3672 1.1 christos } 3673 1.1 christos 3674 1.1 christos switch (rpz_type) { 3675 1.1 christos case DNS_RPZ_TYPE_CLIENT_IP: 3676 1.1 christos trig = LIBRPZ_TRIG_CLIENT_IP; 3677 1.3 christos recursed = false; 3678 1.1 christos break; 3679 1.1 christos case DNS_RPZ_TYPE_IP: 3680 1.1 christos trig = LIBRPZ_TRIG_IP; 3681 1.3 christos recursed = true; 3682 1.1 christos break; 3683 1.1 christos case DNS_RPZ_TYPE_NSIP: 3684 1.1 christos trig = LIBRPZ_TRIG_NSIP; 3685 1.3 christos recursed = true; 3686 1.1 christos break; 3687 1.1 christos default: 3688 1.15 christos UNREACHABLE(); 3689 1.1 christos } 3690 1.1 christos 3691 1.1 christos do { 3692 1.1 christos if (!librpz->rsp_push(&emsg, rpsdb->rsp) || 3693 1.1 christos !librpz->ck_ip(&emsg, 3694 1.1 christos netaddr->family == AF_INET 3695 1.9 christos ? (const void *)&netaddr->type.in 3696 1.9 christos : (const void *)&netaddr->type.in6, 3697 1.1 christos netaddr->family, trig, ++rpsdb->hit_id, 3698 1.1 christos recursed, rpsdb->rsp) || 3699 1.1 christos (res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0) 3700 1.1 christos { 3701 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL, 3702 1.1 christos rpz_type, emsg.c, DNS_R_SERVFAIL); 3703 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 3704 1.23 christos return DNS_R_SERVFAIL; 3705 1.1 christos } 3706 1.1 christos } while (res != 0); 3707 1.23 christos return ISC_R_SUCCESS; 3708 1.1 christos } 3709 1.1 christos 3710 1.1 christos static isc_result_t 3711 1.9 christos dnsrps_rewrite_name(ns_client_t *client, dns_name_t *trig_name, bool recursed, 3712 1.9 christos dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp) { 3713 1.1 christos dns_rpz_st_t *st; 3714 1.23 christos dns_rpsdb_t *rpsdb; 3715 1.1 christos librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP; 3716 1.1 christos isc_region_t r; 3717 1.1 christos int res; 3718 1.1 christos librpz_emsg_t emsg; 3719 1.1 christos isc_result_t result; 3720 1.1 christos 3721 1.23 christos CTRACE(ISC_LOG_DEBUG(3), "dnsrps_rewrite_name"); 3722 1.23 christos 3723 1.1 christos st = client->query.rpz_st; 3724 1.23 christos rpsdb = (dns_rpsdb_t *)st->rpsdb; 3725 1.1 christos 3726 1.1 christos result = rpz_ready(client, p_rdatasetp); 3727 1.1 christos if (result != ISC_R_SUCCESS) { 3728 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 3729 1.23 christos return result; 3730 1.1 christos } 3731 1.1 christos 3732 1.1 christos switch (rpz_type) { 3733 1.1 christos case DNS_RPZ_TYPE_QNAME: 3734 1.1 christos trig = LIBRPZ_TRIG_QNAME; 3735 1.1 christos break; 3736 1.1 christos case DNS_RPZ_TYPE_NSDNAME: 3737 1.1 christos trig = LIBRPZ_TRIG_NSDNAME; 3738 1.1 christos break; 3739 1.1 christos default: 3740 1.15 christos UNREACHABLE(); 3741 1.1 christos } 3742 1.1 christos 3743 1.1 christos dns_name_toregion(trig_name, &r); 3744 1.1 christos do { 3745 1.1 christos if (!librpz->rsp_push(&emsg, rpsdb->rsp) || 3746 1.9 christos !librpz->ck_domain(&emsg, r.base, r.length, trig, 3747 1.9 christos ++rpsdb->hit_id, recursed, rpsdb->rsp) || 3748 1.1 christos (res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0) 3749 1.1 christos { 3750 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL, 3751 1.1 christos rpz_type, emsg.c, DNS_R_SERVFAIL); 3752 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 3753 1.23 christos return DNS_R_SERVFAIL; 3754 1.1 christos } 3755 1.1 christos } while (res != 0); 3756 1.23 christos return ISC_R_SUCCESS; 3757 1.1 christos } 3758 1.1 christos #endif /* USE_DNSRPS */ 3759 1.1 christos 3760 1.1 christos /* 3761 1.1 christos * Check this address in every eligible policy zone. 3762 1.1 christos */ 3763 1.1 christos static isc_result_t 3764 1.1 christos rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr, 3765 1.1 christos dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, 3766 1.9 christos dns_rpz_zbits_t zbits, dns_rdataset_t **p_rdatasetp) { 3767 1.1 christos dns_rpz_zones_t *rpzs; 3768 1.1 christos dns_rpz_st_t *st; 3769 1.1 christos dns_rpz_zone_t *rpz; 3770 1.1 christos dns_rpz_prefix_t prefix; 3771 1.1 christos dns_rpz_num_t rpz_num; 3772 1.1 christos dns_fixedname_t ip_namef, p_namef; 3773 1.1 christos dns_name_t *ip_name, *p_name; 3774 1.1 christos dns_zone_t *p_zone; 3775 1.1 christos dns_db_t *p_db; 3776 1.1 christos dns_dbversion_t *p_version; 3777 1.1 christos dns_dbnode_t *p_node; 3778 1.1 christos dns_rpz_policy_t policy; 3779 1.1 christos isc_result_t result; 3780 1.1 christos 3781 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip"); 3782 1.1 christos 3783 1.1 christos rpzs = client->view->rpzs; 3784 1.1 christos st = client->query.rpz_st; 3785 1.1 christos #ifdef USE_DNSRPS 3786 1.1 christos if (st->popt.dnsrps_enabled) { 3787 1.23 christos return dnsrps_rewrite_ip(client, netaddr, rpz_type, 3788 1.23 christos p_rdatasetp); 3789 1.1 christos } 3790 1.9 christos #endif /* ifdef USE_DNSRPS */ 3791 1.1 christos 3792 1.1 christos ip_name = dns_fixedname_initname(&ip_namef); 3793 1.1 christos 3794 1.1 christos p_zone = NULL; 3795 1.1 christos p_db = NULL; 3796 1.1 christos p_node = NULL; 3797 1.1 christos 3798 1.1 christos while (zbits != 0) { 3799 1.1 christos rpz_num = dns_rpz_find_ip(rpzs, rpz_type, zbits, netaddr, 3800 1.1 christos ip_name, &prefix); 3801 1.9 christos if (rpz_num == DNS_RPZ_INVALID_NUM) { 3802 1.1 christos break; 3803 1.9 christos } 3804 1.1 christos zbits &= (DNS_RPZ_ZMASK(rpz_num) >> 1); 3805 1.1 christos 3806 1.1 christos /* 3807 1.1 christos * Do not try applying policy zones that cannot replace a 3808 1.1 christos * previously found policy zone. 3809 1.1 christos * Stop looking if the next best choice cannot 3810 1.1 christos * replace what we already have. 3811 1.1 christos */ 3812 1.1 christos rpz = rpzs->zones[rpz_num]; 3813 1.1 christos if (st->m.policy != DNS_RPZ_POLICY_MISS) { 3814 1.9 christos if (st->m.rpz->num < rpz->num) { 3815 1.1 christos break; 3816 1.9 christos } 3817 1.1 christos if (st->m.rpz->num == rpz->num && 3818 1.9 christos (st->m.type < rpz_type || st->m.prefix > prefix)) 3819 1.9 christos { 3820 1.1 christos break; 3821 1.9 christos } 3822 1.1 christos } 3823 1.1 christos 3824 1.1 christos /* 3825 1.1 christos * Get the policy for a prefix at least as long 3826 1.1 christos * as the prefix of the entry we had before. 3827 1.1 christos */ 3828 1.1 christos p_name = dns_fixedname_initname(&p_namef); 3829 1.1 christos result = rpz_get_p_name(client, p_name, rpz, rpz_type, ip_name); 3830 1.9 christos if (result != ISC_R_SUCCESS) { 3831 1.1 christos continue; 3832 1.9 christos } 3833 1.9 christos result = rpz_find_p(client, ip_name, qtype, p_name, rpz, 3834 1.9 christos rpz_type, &p_zone, &p_db, &p_version, 3835 1.9 christos &p_node, p_rdatasetp, &policy); 3836 1.1 christos switch (result) { 3837 1.1 christos case DNS_R_NXDOMAIN: 3838 1.1 christos /* 3839 1.1 christos * Continue after a policy record that is missing 3840 1.1 christos * contrary to the summary data. The summary 3841 1.1 christos * data can out of date during races with and among 3842 1.1 christos * policy zone updates. 3843 1.1 christos */ 3844 1.9 christos CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip: mismatched " 3845 1.9 christos "summary data; " 3846 1.9 christos "continuing"); 3847 1.1 christos continue; 3848 1.1 christos case DNS_R_SERVFAIL: 3849 1.1 christos rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp); 3850 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 3851 1.23 christos return DNS_R_SERVFAIL; 3852 1.1 christos default: 3853 1.1 christos /* 3854 1.1 christos * Forget this policy if it is not preferable 3855 1.1 christos * to the previously found policy. 3856 1.1 christos * If this policy is not good, then stop looking 3857 1.1 christos * because none of the later policy zones would work. 3858 1.1 christos * 3859 1.1 christos * With more than one applicable policy, prefer 3860 1.1 christos * the earliest configured policy, 3861 1.1 christos * client-IP over QNAME over IP over NSDNAME over NSIP, 3862 1.1 christos * the longest prefix 3863 1.1 christos * the lexically smallest address. 3864 1.1 christos * dns_rpz_find_ip() ensures st->m.rpz->num >= rpz->num. 3865 1.1 christos * We can compare new and current p_name because 3866 1.1 christos * both are of the same type and in the same zone. 3867 1.1 christos * The tests above eliminate other reasons to 3868 1.1 christos * reject this policy. If this policy can't work, 3869 1.1 christos * then neither can later zones. 3870 1.1 christos */ 3871 1.1 christos if (st->m.policy != DNS_RPZ_POLICY_MISS && 3872 1.1 christos rpz->num == st->m.rpz->num && 3873 1.9 christos (st->m.type == rpz_type && st->m.prefix == prefix && 3874 1.9 christos 0 > dns_name_rdatacompare(st->p_name, p_name))) 3875 1.9 christos { 3876 1.1 christos break; 3877 1.9 christos } 3878 1.1 christos 3879 1.1 christos /* 3880 1.1 christos * Stop checking after saving an enabled hit in this 3881 1.1 christos * policy zone. The radix tree in the policy zone 3882 1.1 christos * ensures that we found the longest match. 3883 1.1 christos */ 3884 1.1 christos if (rpz->policy != DNS_RPZ_POLICY_DISABLED) { 3885 1.9 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip: " 3886 1.9 christos "rpz_save_p"); 3887 1.9 christos rpz_save_p(st, rpz, rpz_type, policy, p_name, 3888 1.9 christos prefix, result, &p_zone, &p_db, 3889 1.9 christos &p_node, p_rdatasetp, p_version); 3890 1.1 christos break; 3891 1.1 christos } 3892 1.1 christos 3893 1.1 christos /* 3894 1.1 christos * Log DNS_RPZ_POLICY_DISABLED zones 3895 1.1 christos * and try the next eligible policy zone. 3896 1.1 christos */ 3897 1.9 christos rpz_log_rewrite(client, true, policy, rpz_type, p_zone, 3898 1.9 christos p_name, NULL, rpz_num); 3899 1.1 christos } 3900 1.1 christos } 3901 1.1 christos 3902 1.1 christos rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp); 3903 1.23 christos return ISC_R_SUCCESS; 3904 1.1 christos } 3905 1.1 christos 3906 1.1 christos /* 3907 1.1 christos * Check the IP addresses in the A or AAAA rrsets for name against 3908 1.1 christos * all eligible rpz_type (IP or NSIP) response policy rewrite rules. 3909 1.1 christos */ 3910 1.1 christos static isc_result_t 3911 1.9 christos rpz_rewrite_ip_rrset(ns_client_t *client, dns_name_t *name, 3912 1.9 christos dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, 3913 1.9 christos dns_rdatatype_t ip_type, dns_db_t **ip_dbp, 3914 1.9 christos dns_dbversion_t *ip_version, dns_rdataset_t **ip_rdatasetp, 3915 1.9 christos dns_rdataset_t **p_rdatasetp, bool resuming) { 3916 1.1 christos dns_rpz_zbits_t zbits; 3917 1.1 christos isc_netaddr_t netaddr; 3918 1.1 christos struct in_addr ina; 3919 1.1 christos struct in6_addr in6a; 3920 1.1 christos isc_result_t result; 3921 1.16 christos unsigned int options = client->query.dboptions | DNS_DBFIND_GLUEOK; 3922 1.15 christos bool done = false; 3923 1.1 christos 3924 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrset"); 3925 1.1 christos 3926 1.15 christos do { 3927 1.15 christos zbits = rpz_get_zbits(client, ip_type, rpz_type); 3928 1.15 christos if (zbits == 0) { 3929 1.23 christos return ISC_R_SUCCESS; 3930 1.15 christos } 3931 1.1 christos 3932 1.15 christos /* 3933 1.15 christos * Get the A or AAAA rdataset. 3934 1.15 christos */ 3935 1.15 christos result = rpz_rrset_find(client, name, ip_type, options, 3936 1.15 christos rpz_type, ip_dbp, ip_version, 3937 1.15 christos ip_rdatasetp, resuming); 3938 1.15 christos switch (result) { 3939 1.15 christos case ISC_R_SUCCESS: 3940 1.15 christos case DNS_R_GLUE: 3941 1.15 christos case DNS_R_ZONECUT: 3942 1.15 christos break; 3943 1.15 christos case DNS_R_EMPTYNAME: 3944 1.15 christos case DNS_R_EMPTYWILD: 3945 1.15 christos case DNS_R_NXDOMAIN: 3946 1.15 christos case DNS_R_NCACHENXDOMAIN: 3947 1.15 christos case DNS_R_NXRRSET: 3948 1.15 christos case DNS_R_NCACHENXRRSET: 3949 1.15 christos case ISC_R_NOTFOUND: 3950 1.23 christos return ISC_R_SUCCESS; 3951 1.15 christos case DNS_R_DELEGATION: 3952 1.15 christos case DNS_R_DUPLICATE: 3953 1.15 christos case DNS_R_DROP: 3954 1.23 christos return result; 3955 1.15 christos case DNS_R_CNAME: 3956 1.15 christos case DNS_R_DNAME: 3957 1.15 christos rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, 3958 1.3 christos rpz_type, "NS address rewrite rrset", 3959 1.1 christos result); 3960 1.23 christos return ISC_R_SUCCESS; 3961 1.15 christos default: 3962 1.15 christos if (client->query.rpz_st->m.policy != 3963 1.16 christos DNS_RPZ_POLICY_ERROR) 3964 1.16 christos { 3965 1.15 christos client->query.rpz_st->m.policy = 3966 1.15 christos DNS_RPZ_POLICY_ERROR; 3967 1.15 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, 3968 1.15 christos rpz_type, 3969 1.15 christos "NS address rewrite rrset", 3970 1.15 christos result); 3971 1.15 christos } 3972 1.15 christos CTRACE(ISC_LOG_ERROR, 3973 1.15 christos "rpz_rewrite_ip_rrset: unexpected " 3974 1.15 christos "result"); 3975 1.23 christos return DNS_R_SERVFAIL; 3976 1.1 christos } 3977 1.1 christos 3978 1.15 christos /* 3979 1.15 christos * If we are processing glue setup for the next loop 3980 1.15 christos * otherwise we are done. 3981 1.15 christos */ 3982 1.15 christos if (result == DNS_R_GLUE) { 3983 1.16 christos options = client->query.dboptions; 3984 1.15 christos } else { 3985 1.16 christos options = client->query.dboptions | DNS_DBFIND_GLUEOK; 3986 1.15 christos done = true; 3987 1.1 christos } 3988 1.1 christos 3989 1.15 christos /* 3990 1.15 christos * Check all of the IP addresses in the rdataset. 3991 1.15 christos */ 3992 1.15 christos for (result = dns_rdataset_first(*ip_rdatasetp); 3993 1.15 christos result == ISC_R_SUCCESS; 3994 1.15 christos result = dns_rdataset_next(*ip_rdatasetp)) 3995 1.15 christos { 3996 1.15 christos dns_rdata_t rdata = DNS_RDATA_INIT; 3997 1.15 christos dns_rdataset_current(*ip_rdatasetp, &rdata); 3998 1.15 christos switch (rdata.type) { 3999 1.15 christos case dns_rdatatype_a: 4000 1.15 christos INSIST(rdata.length == 4); 4001 1.15 christos memmove(&ina.s_addr, rdata.data, 4); 4002 1.15 christos isc_netaddr_fromin(&netaddr, &ina); 4003 1.15 christos break; 4004 1.15 christos case dns_rdatatype_aaaa: 4005 1.15 christos INSIST(rdata.length == 16); 4006 1.15 christos memmove(in6a.s6_addr, rdata.data, 16); 4007 1.15 christos isc_netaddr_fromin6(&netaddr, &in6a); 4008 1.15 christos break; 4009 1.15 christos default: 4010 1.15 christos continue; 4011 1.15 christos } 4012 1.15 christos 4013 1.15 christos result = rpz_rewrite_ip(client, &netaddr, qtype, 4014 1.15 christos rpz_type, zbits, p_rdatasetp); 4015 1.15 christos if (result != ISC_R_SUCCESS) { 4016 1.23 christos return result; 4017 1.15 christos } 4018 1.9 christos } 4019 1.15 christos } while (!done && 4020 1.15 christos client->query.rpz_st->m.policy == DNS_RPZ_POLICY_MISS); 4021 1.1 christos 4022 1.23 christos return ISC_R_SUCCESS; 4023 1.1 christos } 4024 1.1 christos 4025 1.1 christos /* 4026 1.1 christos * Look for IP addresses in A and AAAA rdatasets 4027 1.1 christos * that trigger all eligible IP or NSIP policy rules. 4028 1.1 christos */ 4029 1.1 christos static isc_result_t 4030 1.1 christos rpz_rewrite_ip_rrsets(ns_client_t *client, dns_name_t *name, 4031 1.1 christos dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, 4032 1.9 christos dns_rdataset_t **ip_rdatasetp, bool resuming) { 4033 1.1 christos dns_rpz_st_t *st; 4034 1.1 christos dns_dbversion_t *ip_version; 4035 1.1 christos dns_db_t *ip_db; 4036 1.1 christos dns_rdataset_t *p_rdataset; 4037 1.1 christos isc_result_t result; 4038 1.1 christos 4039 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrsets"); 4040 1.1 christos 4041 1.1 christos st = client->query.rpz_st; 4042 1.1 christos ip_version = NULL; 4043 1.1 christos ip_db = NULL; 4044 1.1 christos p_rdataset = NULL; 4045 1.1 christos if ((st->state & DNS_RPZ_DONE_IPv4) == 0 && 4046 1.9 christos (qtype == dns_rdatatype_a || qtype == dns_rdatatype_any || 4047 1.9 christos rpz_type == DNS_RPZ_TYPE_NSIP)) 4048 1.9 christos { 4049 1.1 christos /* 4050 1.1 christos * Rewrite based on an IPv4 address that will appear 4051 1.1 christos * in the ANSWER section or if we are checking IP addresses. 4052 1.1 christos */ 4053 1.9 christos result = rpz_rewrite_ip_rrset( 4054 1.9 christos client, name, qtype, rpz_type, dns_rdatatype_a, &ip_db, 4055 1.9 christos ip_version, ip_rdatasetp, &p_rdataset, resuming); 4056 1.9 christos if (result == ISC_R_SUCCESS) { 4057 1.1 christos st->state |= DNS_RPZ_DONE_IPv4; 4058 1.9 christos } 4059 1.1 christos } else { 4060 1.1 christos result = ISC_R_SUCCESS; 4061 1.1 christos } 4062 1.1 christos if (result == ISC_R_SUCCESS && 4063 1.9 christos (qtype == dns_rdatatype_aaaa || qtype == dns_rdatatype_any || 4064 1.9 christos rpz_type == DNS_RPZ_TYPE_NSIP)) 4065 1.9 christos { 4066 1.1 christos /* 4067 1.1 christos * Rewrite based on IPv6 addresses that will appear 4068 1.1 christos * in the ANSWER section or if we are checking IP addresses. 4069 1.1 christos */ 4070 1.9 christos result = rpz_rewrite_ip_rrset(client, name, qtype, rpz_type, 4071 1.9 christos dns_rdatatype_aaaa, &ip_db, 4072 1.9 christos ip_version, ip_rdatasetp, 4073 1.1 christos &p_rdataset, resuming); 4074 1.1 christos } 4075 1.9 christos if (ip_db != NULL) { 4076 1.1 christos dns_db_detach(&ip_db); 4077 1.9 christos } 4078 1.3 christos ns_client_putrdataset(client, &p_rdataset); 4079 1.23 christos return result; 4080 1.1 christos } 4081 1.1 christos 4082 1.1 christos /* 4083 1.1 christos * Try to rewrite a request for a qtype rdataset based on the trigger name 4084 1.1 christos * trig_name and rpz_type (DNS_RPZ_TYPE_QNAME or DNS_RPZ_TYPE_NSDNAME). 4085 1.1 christos * Record the results including the replacement rdataset if any 4086 1.1 christos * in client->query.rpz_st. 4087 1.1 christos * *rdatasetp is a scratch rdataset. 4088 1.1 christos */ 4089 1.1 christos static isc_result_t 4090 1.1 christos rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name, 4091 1.1 christos dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, 4092 1.3 christos dns_rpz_zbits_t allowed_zbits, bool recursed, 4093 1.9 christos dns_rdataset_t **rdatasetp) { 4094 1.1 christos dns_rpz_zones_t *rpzs; 4095 1.1 christos dns_rpz_zone_t *rpz; 4096 1.1 christos dns_rpz_st_t *st; 4097 1.1 christos dns_fixedname_t p_namef; 4098 1.1 christos dns_name_t *p_name; 4099 1.1 christos dns_rpz_zbits_t zbits; 4100 1.1 christos dns_rpz_num_t rpz_num; 4101 1.1 christos dns_zone_t *p_zone; 4102 1.1 christos dns_db_t *p_db; 4103 1.1 christos dns_dbversion_t *p_version; 4104 1.1 christos dns_dbnode_t *p_node; 4105 1.1 christos dns_rpz_policy_t policy; 4106 1.1 christos isc_result_t result; 4107 1.1 christos 4108 1.1 christos #ifndef USE_DNSRPS 4109 1.1 christos UNUSED(recursed); 4110 1.9 christos #endif /* ifndef USE_DNSRPS */ 4111 1.1 christos 4112 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name"); 4113 1.1 christos 4114 1.1 christos rpzs = client->view->rpzs; 4115 1.1 christos st = client->query.rpz_st; 4116 1.1 christos 4117 1.1 christos #ifdef USE_DNSRPS 4118 1.1 christos if (st->popt.dnsrps_enabled) { 4119 1.23 christos return dnsrps_rewrite_name(client, trig_name, recursed, 4120 1.23 christos rpz_type, rdatasetp); 4121 1.1 christos } 4122 1.9 christos #endif /* ifdef USE_DNSRPS */ 4123 1.1 christos 4124 1.1 christos zbits = rpz_get_zbits(client, qtype, rpz_type); 4125 1.1 christos zbits &= allowed_zbits; 4126 1.9 christos if (zbits == 0) { 4127 1.23 christos return ISC_R_SUCCESS; 4128 1.9 christos } 4129 1.1 christos 4130 1.1 christos /* 4131 1.1 christos * Use the summary database to find the bit mask of policy zones 4132 1.1 christos * with policies for this trigger name. We do this even if there 4133 1.1 christos * is only one eligible policy zone so that wildcard triggers 4134 1.1 christos * are matched correctly, and not into their parent. 4135 1.1 christos */ 4136 1.1 christos zbits = dns_rpz_find_name(rpzs, rpz_type, zbits, trig_name); 4137 1.9 christos if (zbits == 0) { 4138 1.23 christos return ISC_R_SUCCESS; 4139 1.9 christos } 4140 1.1 christos 4141 1.1 christos p_name = dns_fixedname_initname(&p_namef); 4142 1.1 christos 4143 1.1 christos p_zone = NULL; 4144 1.1 christos p_db = NULL; 4145 1.1 christos p_node = NULL; 4146 1.1 christos 4147 1.1 christos /* 4148 1.1 christos * Check the trigger name in every policy zone that the summary data 4149 1.1 christos * says has a hit for the trigger name. 4150 1.1 christos * Most of the time there are no eligible zones and the summary data 4151 1.1 christos * keeps us from getting this far. 4152 1.1 christos * We check the most eligible zone first and so usually check only 4153 1.1 christos * one policy zone. 4154 1.1 christos */ 4155 1.1 christos for (rpz_num = 0; zbits != 0; ++rpz_num, zbits >>= 1) { 4156 1.9 christos if ((zbits & 1) == 0) { 4157 1.1 christos continue; 4158 1.9 christos } 4159 1.1 christos 4160 1.1 christos /* 4161 1.1 christos * Do not check policy zones that cannot replace a previously 4162 1.1 christos * found policy. 4163 1.1 christos */ 4164 1.1 christos rpz = rpzs->zones[rpz_num]; 4165 1.1 christos if (st->m.policy != DNS_RPZ_POLICY_MISS) { 4166 1.9 christos if (st->m.rpz->num < rpz->num) { 4167 1.1 christos break; 4168 1.9 christos } 4169 1.9 christos if (st->m.rpz->num == rpz->num && st->m.type < rpz_type) 4170 1.9 christos { 4171 1.1 christos break; 4172 1.9 christos } 4173 1.1 christos } 4174 1.1 christos 4175 1.1 christos /* 4176 1.1 christos * Get the next policy zone's record for this trigger name. 4177 1.1 christos */ 4178 1.1 christos result = rpz_get_p_name(client, p_name, rpz, rpz_type, 4179 1.1 christos trig_name); 4180 1.9 christos if (result != ISC_R_SUCCESS) { 4181 1.1 christos continue; 4182 1.9 christos } 4183 1.9 christos result = rpz_find_p(client, trig_name, qtype, p_name, rpz, 4184 1.9 christos rpz_type, &p_zone, &p_db, &p_version, 4185 1.9 christos &p_node, rdatasetp, &policy); 4186 1.1 christos switch (result) { 4187 1.1 christos case DNS_R_NXDOMAIN: 4188 1.1 christos /* 4189 1.1 christos * Continue after a missing policy record 4190 1.1 christos * contrary to the summary data. The summary 4191 1.1 christos * data can out of date during races with and among 4192 1.1 christos * policy zone updates. 4193 1.1 christos */ 4194 1.9 christos CTRACE(ISC_LOG_ERROR, "rpz_rewrite_name: mismatched " 4195 1.9 christos "summary data; " 4196 1.9 christos "continuing"); 4197 1.1 christos continue; 4198 1.1 christos case DNS_R_SERVFAIL: 4199 1.1 christos rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); 4200 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 4201 1.23 christos return DNS_R_SERVFAIL; 4202 1.1 christos default: 4203 1.1 christos /* 4204 1.1 christos * With more than one applicable policy, prefer 4205 1.1 christos * the earliest configured policy, 4206 1.1 christos * client-IP over QNAME over IP over NSDNAME over NSIP, 4207 1.1 christos * and the smallest name. 4208 1.1 christos * We known st->m.rpz->num >= rpz->num and either 4209 1.1 christos * st->m.rpz->num > rpz->num or st->m.type >= rpz_type 4210 1.1 christos */ 4211 1.1 christos if (st->m.policy != DNS_RPZ_POLICY_MISS && 4212 1.1 christos rpz->num == st->m.rpz->num && 4213 1.1 christos (st->m.type < rpz_type || 4214 1.1 christos (st->m.type == rpz_type && 4215 1.1 christos 0 >= dns_name_compare(p_name, st->p_name)))) 4216 1.9 christos { 4217 1.1 christos continue; 4218 1.9 christos } 4219 1.4 christos 4220 1.1 christos if (rpz->policy != DNS_RPZ_POLICY_DISABLED) { 4221 1.9 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name: " 4222 1.9 christos "rpz_save_p"); 4223 1.9 christos rpz_save_p(st, rpz, rpz_type, policy, p_name, 0, 4224 1.9 christos result, &p_zone, &p_db, &p_node, 4225 1.1 christos rdatasetp, p_version); 4226 1.1 christos /* 4227 1.1 christos * After a hit, higher numbered policy zones 4228 1.1 christos * are irrelevant 4229 1.1 christos */ 4230 1.1 christos rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); 4231 1.23 christos return ISC_R_SUCCESS; 4232 1.1 christos } 4233 1.1 christos /* 4234 1.1 christos * Log DNS_RPZ_POLICY_DISABLED zones 4235 1.1 christos * and try the next eligible policy zone. 4236 1.1 christos */ 4237 1.9 christos rpz_log_rewrite(client, true, policy, rpz_type, p_zone, 4238 1.9 christos p_name, NULL, rpz_num); 4239 1.1 christos break; 4240 1.1 christos } 4241 1.1 christos } 4242 1.1 christos 4243 1.1 christos rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); 4244 1.23 christos return ISC_R_SUCCESS; 4245 1.1 christos } 4246 1.1 christos 4247 1.1 christos static void 4248 1.1 christos rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname, 4249 1.9 christos isc_result_t result, int level, const char *str) { 4250 1.1 christos dns_rpz_st_t *st; 4251 1.1 christos 4252 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ns_skip"); 4253 1.1 christos 4254 1.1 christos st = client->query.rpz_st; 4255 1.1 christos 4256 1.9 christos if (str != NULL) { 4257 1.9 christos rpz_log_fail_helper(client, level, nsname, DNS_RPZ_TYPE_NSIP, 4258 1.9 christos DNS_RPZ_TYPE_NSDNAME, str, result); 4259 1.9 christos } 4260 1.1 christos if (st->r.ns_rdataset != NULL && 4261 1.16 christos dns_rdataset_isassociated(st->r.ns_rdataset)) 4262 1.16 christos { 4263 1.1 christos dns_rdataset_disassociate(st->r.ns_rdataset); 4264 1.9 christos } 4265 1.1 christos 4266 1.1 christos st->r.label--; 4267 1.1 christos } 4268 1.1 christos 4269 1.1 christos /* 4270 1.1 christos * RPZ query result types 4271 1.1 christos */ 4272 1.1 christos typedef enum { 4273 1.1 christos qresult_type_done = 0, 4274 1.1 christos qresult_type_restart = 1, 4275 1.1 christos qresult_type_recurse = 2 4276 1.1 christos } qresult_type_t; 4277 1.1 christos 4278 1.1 christos /* 4279 1.1 christos * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting. 4280 1.1 christos */ 4281 1.1 christos static isc_result_t 4282 1.9 christos rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, 4283 1.9 christos bool resuming, dns_rdataset_t *ordataset, dns_rdataset_t *osigset) { 4284 1.1 christos dns_rpz_zones_t *rpzs; 4285 1.1 christos dns_rpz_st_t *st; 4286 1.26 christos dns_rdataset_t *rdataset = NULL; 4287 1.1 christos dns_fixedname_t nsnamef; 4288 1.1 christos dns_name_t *nsname; 4289 1.26 christos qresult_type_t qresult_type = qresult_type_done; 4290 1.1 christos dns_rpz_zbits_t zbits; 4291 1.1 christos isc_result_t result = ISC_R_SUCCESS; 4292 1.1 christos dns_rpz_have_t have; 4293 1.1 christos dns_rpz_popt_t popt; 4294 1.26 christos bool first_time; 4295 1.26 christos dns_rpz_num_t zones_registered; 4296 1.26 christos dns_rpz_num_t zones_processed; 4297 1.26 christos 4298 1.1 christos int rpz_ver; 4299 1.15 christos unsigned int options; 4300 1.1 christos #ifdef USE_DNSRPS 4301 1.1 christos librpz_emsg_t emsg; 4302 1.9 christos #endif /* ifdef USE_DNSRPS */ 4303 1.1 christos 4304 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite"); 4305 1.1 christos 4306 1.1 christos rpzs = client->view->rpzs; 4307 1.1 christos st = client->query.rpz_st; 4308 1.1 christos 4309 1.13 christos if (rpzs == NULL) { 4310 1.23 christos return ISC_R_NOTFOUND; 4311 1.13 christos } 4312 1.13 christos if (st != NULL && (st->state & DNS_RPZ_REWRITTEN) != 0) { 4313 1.23 christos return DNS_R_DISALLOWED; 4314 1.13 christos } 4315 1.13 christos if (RECURSING(client)) { 4316 1.23 christos return DNS_R_DISALLOWED; 4317 1.9 christos } 4318 1.1 christos 4319 1.1 christos RWLOCK(&rpzs->search_lock, isc_rwlocktype_read); 4320 1.1 christos if ((rpzs->p.num_zones == 0 && !rpzs->p.dnsrps_enabled) || 4321 1.1 christos (!RECURSIONOK(client) && rpzs->p.no_rd_ok == 0) || 4322 1.1 christos !rpz_ck_dnssec(client, qresult, ordataset, osigset)) 4323 1.1 christos { 4324 1.1 christos RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read); 4325 1.23 christos return DNS_R_DISALLOWED; 4326 1.1 christos } 4327 1.1 christos have = rpzs->have; 4328 1.1 christos popt = rpzs->p; 4329 1.26 christos first_time = rpzs->first_time; 4330 1.26 christos zones_registered = atomic_load_acquire(&rpzs->zones_registered); 4331 1.26 christos zones_processed = atomic_load_acquire(&rpzs->zones_processed); 4332 1.1 christos rpz_ver = rpzs->rpz_ver; 4333 1.1 christos RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read); 4334 1.1 christos 4335 1.1 christos #ifndef USE_DNSRPS 4336 1.1 christos INSIST(!popt.dnsrps_enabled); 4337 1.9 christos #endif /* ifndef USE_DNSRPS */ 4338 1.1 christos 4339 1.1 christos if (st == NULL) { 4340 1.23 christos st = isc_mem_get(client->manager->mctx, sizeof(*st)); 4341 1.1 christos st->state = 0; 4342 1.1 christos st->rpsdb = NULL; 4343 1.1 christos } 4344 1.1 christos if (st->state == 0) { 4345 1.1 christos st->state |= DNS_RPZ_ACTIVE; 4346 1.1 christos memset(&st->m, 0, sizeof(st->m)); 4347 1.1 christos st->m.type = DNS_RPZ_TYPE_BAD; 4348 1.1 christos st->m.policy = DNS_RPZ_POLICY_MISS; 4349 1.1 christos st->m.ttl = ~0; 4350 1.1 christos memset(&st->r, 0, sizeof(st->r)); 4351 1.1 christos memset(&st->q, 0, sizeof(st->q)); 4352 1.1 christos st->p_name = dns_fixedname_initname(&st->_p_namef); 4353 1.1 christos st->r_name = dns_fixedname_initname(&st->_r_namef); 4354 1.1 christos st->fname = dns_fixedname_initname(&st->_fnamef); 4355 1.1 christos st->have = have; 4356 1.1 christos st->popt = popt; 4357 1.1 christos st->rpz_ver = rpz_ver; 4358 1.1 christos client->query.rpz_st = st; 4359 1.1 christos #ifdef USE_DNSRPS 4360 1.1 christos if (popt.dnsrps_enabled) { 4361 1.1 christos if (st->rpsdb != NULL) { 4362 1.1 christos dns_db_detach(&st->rpsdb); 4363 1.1 christos } 4364 1.23 christos CTRACE(ISC_LOG_DEBUG(3), "dns_dnsrps_rewrite_init"); 4365 1.9 christos result = dns_dnsrps_rewrite_init( 4366 1.9 christos &emsg, st, rpzs, client->query.qname, 4367 1.23 christos client->manager->mctx, RECURSIONOK(client)); 4368 1.1 christos if (result != ISC_R_SUCCESS) { 4369 1.9 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL, 4370 1.9 christos DNS_RPZ_TYPE_QNAME, emsg.c, 4371 1.9 christos result); 4372 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 4373 1.23 christos return ISC_R_SUCCESS; 4374 1.1 christos } 4375 1.1 christos } 4376 1.9 christos #endif /* ifdef USE_DNSRPS */ 4377 1.1 christos } 4378 1.1 christos 4379 1.26 christos /* Check if the initial loading of RPZ is complete. */ 4380 1.26 christos if (first_time && popt.servfail_until_ready && 4381 1.26 christos zones_processed < zones_registered) 4382 1.26 christos { 4383 1.26 christos /* Do not pollute SERVFAIL cache */ 4384 1.26 christos client->attributes |= NS_CLIENTATTR_NOSETFC; 4385 1.26 christos 4386 1.26 christos if (can_log_rpznotready()) { 4387 1.26 christos rpz_log_fail(client, DNS_RPZ_INFO_LEVEL, NULL, 4388 1.26 christos DNS_RPZ_TYPE_QNAME, 4389 1.26 christos "RPZ servfail-until-ready", DNS_R_WAIT); 4390 1.26 christos } 4391 1.26 christos 4392 1.26 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 4393 1.26 christos goto cleanup; 4394 1.26 christos } 4395 1.26 christos 4396 1.1 christos /* 4397 1.1 christos * There is nothing to rewrite if the main query failed. 4398 1.1 christos */ 4399 1.1 christos switch (qresult) { 4400 1.1 christos case ISC_R_SUCCESS: 4401 1.1 christos case DNS_R_GLUE: 4402 1.1 christos case DNS_R_ZONECUT: 4403 1.1 christos qresult_type = qresult_type_done; 4404 1.1 christos break; 4405 1.1 christos case DNS_R_EMPTYNAME: 4406 1.1 christos case DNS_R_NXRRSET: 4407 1.1 christos case DNS_R_NXDOMAIN: 4408 1.1 christos case DNS_R_EMPTYWILD: 4409 1.1 christos case DNS_R_NCACHENXDOMAIN: 4410 1.1 christos case DNS_R_NCACHENXRRSET: 4411 1.3 christos case DNS_R_COVERINGNSEC: 4412 1.1 christos case DNS_R_CNAME: 4413 1.1 christos case DNS_R_DNAME: 4414 1.1 christos qresult_type = qresult_type_restart; 4415 1.1 christos break; 4416 1.1 christos case DNS_R_DELEGATION: 4417 1.1 christos case ISC_R_NOTFOUND: 4418 1.1 christos /* 4419 1.1 christos * If recursion is on, do only tentative rewriting. 4420 1.1 christos * If recursion is off, this the normal and only time we 4421 1.1 christos * can rewrite. 4422 1.1 christos */ 4423 1.9 christos if (RECURSIONOK(client)) { 4424 1.1 christos qresult_type = qresult_type_recurse; 4425 1.9 christos } else { 4426 1.1 christos qresult_type = qresult_type_restart; 4427 1.9 christos } 4428 1.1 christos break; 4429 1.1 christos case ISC_R_FAILURE: 4430 1.1 christos case ISC_R_TIMEDOUT: 4431 1.22 christos case ISC_R_CANCELED: 4432 1.1 christos case DNS_R_BROKENCHAIN: 4433 1.1 christos rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, NULL, 4434 1.1 christos DNS_RPZ_TYPE_QNAME, 4435 1.3 christos "stop on qresult in rpz_rewrite()", qresult); 4436 1.23 christos return ISC_R_SUCCESS; 4437 1.1 christos default: 4438 1.1 christos rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, NULL, 4439 1.1 christos DNS_RPZ_TYPE_QNAME, 4440 1.3 christos "stop on unrecognized qresult in rpz_rewrite()", 4441 1.1 christos qresult); 4442 1.23 christos return ISC_R_SUCCESS; 4443 1.1 christos } 4444 1.1 christos 4445 1.1 christos if ((st->state & (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) != 4446 1.1 christos (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) 4447 1.1 christos { 4448 1.1 christos isc_netaddr_t netaddr; 4449 1.1 christos dns_rpz_zbits_t allowed; 4450 1.1 christos 4451 1.1 christos if (!st->popt.dnsrps_enabled && 4452 1.16 christos qresult_type == qresult_type_recurse) 4453 1.16 christos { 4454 1.1 christos /* 4455 1.1 christos * This request needs recursion that has not been done. 4456 1.1 christos * Get bits for the policy zones that do not need 4457 1.1 christos * to wait for the results of recursion. 4458 1.1 christos */ 4459 1.1 christos allowed = st->have.qname_skip_recurse; 4460 1.1 christos if (allowed == 0) { 4461 1.23 christos return ISC_R_SUCCESS; 4462 1.1 christos } 4463 1.1 christos } else { 4464 1.1 christos allowed = DNS_RPZ_ALL_ZBITS; 4465 1.1 christos } 4466 1.1 christos 4467 1.1 christos /* 4468 1.1 christos * Check once for triggers for the client IP address. 4469 1.1 christos */ 4470 1.1 christos if ((st->state & DNS_RPZ_DONE_CLIENT_IP) == 0) { 4471 1.1 christos zbits = rpz_get_zbits(client, dns_rdatatype_none, 4472 1.1 christos DNS_RPZ_TYPE_CLIENT_IP); 4473 1.1 christos zbits &= allowed; 4474 1.1 christos if (zbits != 0) { 4475 1.1 christos isc_netaddr_fromsockaddr(&netaddr, 4476 1.1 christos &client->peeraddr); 4477 1.1 christos result = rpz_rewrite_ip(client, &netaddr, qtype, 4478 1.1 christos DNS_RPZ_TYPE_CLIENT_IP, 4479 1.1 christos zbits, &rdataset); 4480 1.9 christos if (result != ISC_R_SUCCESS) { 4481 1.1 christos goto cleanup; 4482 1.9 christos } 4483 1.1 christos } 4484 1.1 christos } 4485 1.1 christos 4486 1.1 christos /* 4487 1.1 christos * Check triggers for the query name if this is the first time 4488 1.1 christos * for the current qname. 4489 1.1 christos * There is a first time for each name in a CNAME chain 4490 1.1 christos */ 4491 1.1 christos if ((st->state & DNS_RPZ_DONE_QNAME) == 0) { 4492 1.3 christos bool norec = (qresult_type != qresult_type_recurse); 4493 1.1 christos result = rpz_rewrite_name(client, client->query.qname, 4494 1.1 christos qtype, DNS_RPZ_TYPE_QNAME, 4495 1.9 christos allowed, norec, &rdataset); 4496 1.9 christos if (result != ISC_R_SUCCESS) { 4497 1.1 christos goto cleanup; 4498 1.9 christos } 4499 1.1 christos 4500 1.1 christos /* 4501 1.1 christos * Check IPv4 addresses in A RRs next. 4502 1.1 christos * Reset to the start of the NS names. 4503 1.1 christos */ 4504 1.1 christos st->r.label = dns_name_countlabels(client->query.qname); 4505 1.1 christos st->state &= ~(DNS_RPZ_DONE_QNAME_IP | 4506 1.1 christos DNS_RPZ_DONE_IPv4); 4507 1.1 christos } 4508 1.1 christos 4509 1.1 christos /* 4510 1.1 christos * Quit if this was an attempt to find a qname or 4511 1.1 christos * client-IP trigger before recursion. 4512 1.1 christos * We will be back if no pre-recursion triggers hit. 4513 1.1 christos * For example, consider 2 policy zones, both with qname and 4514 1.1 christos * IP address triggers. If the qname misses the 1st zone, 4515 1.1 christos * then we cannot know whether a hit for the qname in the 4516 1.1 christos * 2nd zone matters until after recursing to get the A RRs and 4517 1.1 christos * testing them in the first zone. 4518 1.1 christos * Do not bother saving the work from this attempt, 4519 1.9 christos * because recursion is so slow. 4520 1.1 christos */ 4521 1.9 christos if (qresult_type == qresult_type_recurse) { 4522 1.1 christos goto cleanup; 4523 1.9 christos } 4524 1.1 christos 4525 1.1 christos /* 4526 1.1 christos * DNS_RPZ_DONE_QNAME but not DNS_RPZ_DONE_CLIENT_IP 4527 1.1 christos * is reset at the end of dealing with each CNAME. 4528 1.1 christos */ 4529 1.1 christos st->state |= (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME); 4530 1.1 christos } 4531 1.1 christos 4532 1.1 christos /* 4533 1.1 christos * Check known IP addresses for the query name if the database lookup 4534 1.1 christos * resulted in some addresses (qresult_type == qresult_type_done) 4535 1.1 christos * and if we have not already checked them. 4536 1.1 christos * Any recursion required for the query has already happened. 4537 1.1 christos * Do not check addresses that will not be in the ANSWER section. 4538 1.1 christos */ 4539 1.1 christos if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 && 4540 1.1 christos qresult_type == qresult_type_done && 4541 1.9 christos rpz_get_zbits(client, qtype, DNS_RPZ_TYPE_IP) != 0) 4542 1.9 christos { 4543 1.9 christos result = rpz_rewrite_ip_rrsets(client, client->query.qname, 4544 1.9 christos qtype, DNS_RPZ_TYPE_IP, 4545 1.1 christos &rdataset, resuming); 4546 1.9 christos if (result != ISC_R_SUCCESS) { 4547 1.1 christos goto cleanup; 4548 1.9 christos } 4549 1.1 christos /* 4550 1.1 christos * We are finished checking the IP addresses for the qname. 4551 1.9 christos * Start with IPv4 if we will check NS IP addresses. 4552 1.1 christos */ 4553 1.1 christos st->state |= DNS_RPZ_DONE_QNAME_IP; 4554 1.1 christos st->state &= ~DNS_RPZ_DONE_IPv4; 4555 1.1 christos } 4556 1.1 christos 4557 1.1 christos /* 4558 1.1 christos * Stop looking for rules if there are none of the other kinds 4559 1.1 christos * that could override what we already have. 4560 1.1 christos */ 4561 1.9 christos if (rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSDNAME) == 4562 1.9 christos 0 && 4563 1.9 christos rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSIP) == 0) 4564 1.9 christos { 4565 1.1 christos result = ISC_R_SUCCESS; 4566 1.1 christos goto cleanup; 4567 1.1 christos } 4568 1.1 christos 4569 1.1 christos dns_fixedname_init(&nsnamef); 4570 1.1 christos dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef)); 4571 1.16 christos options = client->query.dboptions | DNS_DBFIND_GLUEOK; 4572 1.1 christos while (st->r.label > st->popt.min_ns_labels) { 4573 1.15 christos bool was_glue = false; 4574 1.1 christos /* 4575 1.1 christos * Get NS rrset for each domain in the current qname. 4576 1.1 christos */ 4577 1.1 christos if (st->r.label == dns_name_countlabels(client->query.qname)) { 4578 1.1 christos nsname = client->query.qname; 4579 1.1 christos } else { 4580 1.1 christos nsname = dns_fixedname_name(&nsnamef); 4581 1.9 christos dns_name_split(client->query.qname, st->r.label, NULL, 4582 1.9 christos nsname); 4583 1.1 christos } 4584 1.1 christos if (st->r.ns_rdataset == NULL || 4585 1.16 christos !dns_rdataset_isassociated(st->r.ns_rdataset)) 4586 1.16 christos { 4587 1.1 christos dns_db_t *db = NULL; 4588 1.1 christos result = rpz_rrset_find(client, nsname, 4589 1.15 christos dns_rdatatype_ns, options, 4590 1.9 christos DNS_RPZ_TYPE_NSDNAME, &db, NULL, 4591 1.9 christos &st->r.ns_rdataset, resuming); 4592 1.9 christos if (db != NULL) { 4593 1.1 christos dns_db_detach(&db); 4594 1.9 christos } 4595 1.9 christos if (st->m.policy == DNS_RPZ_POLICY_ERROR) { 4596 1.1 christos goto cleanup; 4597 1.9 christos } 4598 1.1 christos switch (result) { 4599 1.15 christos case DNS_R_GLUE: 4600 1.15 christos was_glue = true; 4601 1.15 christos FALLTHROUGH; 4602 1.1 christos case ISC_R_SUCCESS: 4603 1.1 christos result = dns_rdataset_first(st->r.ns_rdataset); 4604 1.9 christos if (result != ISC_R_SUCCESS) { 4605 1.1 christos goto cleanup; 4606 1.9 christos } 4607 1.1 christos st->state &= ~(DNS_RPZ_DONE_NSDNAME | 4608 1.1 christos DNS_RPZ_DONE_IPv4); 4609 1.1 christos break; 4610 1.1 christos case DNS_R_DELEGATION: 4611 1.1 christos case DNS_R_DUPLICATE: 4612 1.1 christos case DNS_R_DROP: 4613 1.1 christos goto cleanup; 4614 1.1 christos case DNS_R_EMPTYNAME: 4615 1.1 christos case DNS_R_NXRRSET: 4616 1.1 christos case DNS_R_EMPTYWILD: 4617 1.1 christos case DNS_R_NXDOMAIN: 4618 1.1 christos case DNS_R_NCACHENXDOMAIN: 4619 1.1 christos case DNS_R_NCACHENXRRSET: 4620 1.1 christos case ISC_R_NOTFOUND: 4621 1.1 christos case DNS_R_CNAME: 4622 1.1 christos case DNS_R_DNAME: 4623 1.9 christos rpz_rewrite_ns_skip(client, nsname, result, 0, 4624 1.9 christos NULL); 4625 1.1 christos continue; 4626 1.1 christos case ISC_R_TIMEDOUT: 4627 1.1 christos case DNS_R_BROKENCHAIN: 4628 1.1 christos case ISC_R_FAILURE: 4629 1.1 christos rpz_rewrite_ns_skip(client, nsname, result, 4630 1.9 christos DNS_RPZ_DEBUG_LEVEL3, 4631 1.9 christos " NS rpz_rrset_find()"); 4632 1.1 christos continue; 4633 1.1 christos default: 4634 1.1 christos rpz_rewrite_ns_skip(client, nsname, result, 4635 1.9 christos DNS_RPZ_INFO_LEVEL, 4636 1.9 christos " unrecognized NS" 4637 1.9 christos " rpz_rrset_find()"); 4638 1.1 christos continue; 4639 1.1 christos } 4640 1.1 christos } 4641 1.15 christos 4642 1.1 christos /* 4643 1.1 christos * Check all NS names. 4644 1.1 christos */ 4645 1.1 christos do { 4646 1.1 christos dns_rdata_ns_t ns; 4647 1.1 christos dns_rdata_t nsrdata = DNS_RDATA_INIT; 4648 1.1 christos 4649 1.1 christos dns_rdataset_current(st->r.ns_rdataset, &nsrdata); 4650 1.1 christos result = dns_rdata_tostruct(&nsrdata, &ns, NULL); 4651 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 4652 1.1 christos dns_rdata_reset(&nsrdata); 4653 1.3 christos 4654 1.1 christos /* 4655 1.1 christos * Do nothing about "NS ." 4656 1.1 christos */ 4657 1.1 christos if (dns_name_equal(&ns.name, dns_rootname)) { 4658 1.1 christos dns_rdata_freestruct(&ns); 4659 1.1 christos result = dns_rdataset_next(st->r.ns_rdataset); 4660 1.1 christos continue; 4661 1.1 christos } 4662 1.1 christos /* 4663 1.1 christos * Check this NS name if we did not handle it 4664 1.1 christos * during a previous recursion. 4665 1.1 christos */ 4666 1.1 christos if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0) { 4667 1.9 christos result = rpz_rewrite_name( 4668 1.9 christos client, &ns.name, qtype, 4669 1.9 christos DNS_RPZ_TYPE_NSDNAME, DNS_RPZ_ALL_ZBITS, 4670 1.9 christos true, &rdataset); 4671 1.1 christos if (result != ISC_R_SUCCESS) { 4672 1.1 christos dns_rdata_freestruct(&ns); 4673 1.1 christos goto cleanup; 4674 1.1 christos } 4675 1.1 christos st->state |= DNS_RPZ_DONE_NSDNAME; 4676 1.1 christos } 4677 1.1 christos /* 4678 1.1 christos * Check all IP addresses for this NS name. 4679 1.1 christos */ 4680 1.1 christos result = rpz_rewrite_ip_rrsets(client, &ns.name, qtype, 4681 1.1 christos DNS_RPZ_TYPE_NSIP, 4682 1.1 christos &rdataset, resuming); 4683 1.1 christos dns_rdata_freestruct(&ns); 4684 1.9 christos if (result != ISC_R_SUCCESS) { 4685 1.1 christos goto cleanup; 4686 1.9 christos } 4687 1.1 christos st->state &= ~(DNS_RPZ_DONE_NSDNAME | 4688 1.1 christos DNS_RPZ_DONE_IPv4); 4689 1.1 christos result = dns_rdataset_next(st->r.ns_rdataset); 4690 1.1 christos } while (result == ISC_R_SUCCESS); 4691 1.1 christos dns_rdataset_disassociate(st->r.ns_rdataset); 4692 1.15 christos 4693 1.15 christos /* 4694 1.15 christos * If we just checked a glue NS RRset retry without allowing 4695 1.15 christos * glue responses, otherwise setup for the next name. 4696 1.15 christos */ 4697 1.15 christos if (was_glue) { 4698 1.16 christos options = client->query.dboptions; 4699 1.15 christos } else { 4700 1.16 christos options = client->query.dboptions | DNS_DBFIND_GLUEOK; 4701 1.15 christos st->r.label--; 4702 1.15 christos } 4703 1.1 christos 4704 1.1 christos if (rpz_get_zbits(client, dns_rdatatype_any, 4705 1.1 christos DNS_RPZ_TYPE_NSDNAME) == 0 && 4706 1.1 christos rpz_get_zbits(client, dns_rdatatype_any, 4707 1.1 christos DNS_RPZ_TYPE_NSIP) == 0) 4708 1.9 christos { 4709 1.1 christos break; 4710 1.9 christos } 4711 1.1 christos } 4712 1.1 christos 4713 1.1 christos /* 4714 1.1 christos * Use the best hit, if any. 4715 1.1 christos */ 4716 1.1 christos result = ISC_R_SUCCESS; 4717 1.1 christos 4718 1.1 christos cleanup: 4719 1.1 christos #ifdef USE_DNSRPS 4720 1.9 christos if (st->popt.dnsrps_enabled && st->m.policy != DNS_RPZ_POLICY_ERROR && 4721 1.1 christos !dnsrps_set_p(&emsg, client, st, qtype, &rdataset, 4722 1.25 christos qresult_type != qresult_type_recurse)) 4723 1.1 christos { 4724 1.1 christos rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL, 4725 1.1 christos DNS_RPZ_TYPE_BAD, emsg.c, DNS_R_SERVFAIL); 4726 1.1 christos st->m.policy = DNS_RPZ_POLICY_ERROR; 4727 1.1 christos } 4728 1.9 christos #endif /* ifdef USE_DNSRPS */ 4729 1.1 christos if (st->m.policy != DNS_RPZ_POLICY_MISS && 4730 1.1 christos st->m.policy != DNS_RPZ_POLICY_ERROR && 4731 1.1 christos st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN) 4732 1.9 christos { 4733 1.1 christos st->m.policy = st->m.rpz->policy; 4734 1.9 christos } 4735 1.1 christos if (st->m.policy == DNS_RPZ_POLICY_MISS || 4736 1.1 christos st->m.policy == DNS_RPZ_POLICY_PASSTHRU || 4737 1.9 christos st->m.policy == DNS_RPZ_POLICY_ERROR) 4738 1.9 christos { 4739 1.1 christos if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU && 4740 1.16 christos result != DNS_R_DELEGATION) 4741 1.16 christos { 4742 1.9 christos rpz_log_rewrite(client, false, st->m.policy, st->m.type, 4743 1.9 christos st->m.zone, st->p_name, NULL, 4744 1.9 christos st->m.rpz->num); 4745 1.9 christos } 4746 1.1 christos rpz_match_clear(st); 4747 1.1 christos } 4748 1.1 christos if (st->m.policy == DNS_RPZ_POLICY_ERROR) { 4749 1.1 christos CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy"); 4750 1.1 christos st->m.type = DNS_RPZ_TYPE_BAD; 4751 1.1 christos result = DNS_R_SERVFAIL; 4752 1.1 christos } 4753 1.3 christos ns_client_putrdataset(client, &rdataset); 4754 1.9 christos if ((st->state & DNS_RPZ_RECURSING) == 0) { 4755 1.1 christos rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset); 4756 1.9 christos } 4757 1.1 christos 4758 1.23 christos return result; 4759 1.1 christos } 4760 1.1 christos 4761 1.1 christos /* 4762 1.1 christos * See if response policy zone rewriting is allowed by a lack of interest 4763 1.1 christos * by the client in DNSSEC or a lack of signatures. 4764 1.1 christos */ 4765 1.3 christos static bool 4766 1.1 christos rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult, 4767 1.9 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 4768 1.1 christos dns_fixedname_t fixed; 4769 1.1 christos dns_name_t *found; 4770 1.1 christos dns_rdataset_t trdataset; 4771 1.1 christos dns_rdatatype_t type; 4772 1.1 christos isc_result_t result; 4773 1.1 christos 4774 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "rpz_ck_dnssec"); 4775 1.1 christos 4776 1.9 christos if (client->view->rpzs->p.break_dnssec || !WANTDNSSEC(client)) { 4777 1.23 christos return true; 4778 1.9 christos } 4779 1.1 christos 4780 1.1 christos /* 4781 1.1 christos * We do not know if there are signatures if we have not recursed 4782 1.1 christos * for them. 4783 1.1 christos */ 4784 1.9 christos if (qresult == DNS_R_DELEGATION || qresult == ISC_R_NOTFOUND) { 4785 1.23 christos return false; 4786 1.9 christos } 4787 1.1 christos 4788 1.9 christos if (sigrdataset == NULL) { 4789 1.23 christos return true; 4790 1.9 christos } 4791 1.9 christos if (dns_rdataset_isassociated(sigrdataset)) { 4792 1.23 christos return false; 4793 1.9 christos } 4794 1.1 christos 4795 1.1 christos /* 4796 1.1 christos * We are happy to rewrite nothing. 4797 1.1 christos */ 4798 1.9 christos if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) { 4799 1.23 christos return true; 4800 1.9 christos } 4801 1.1 christos /* 4802 1.1 christos * Do not rewrite if there is any sign of signatures. 4803 1.1 christos */ 4804 1.1 christos if (rdataset->type == dns_rdatatype_nsec || 4805 1.1 christos rdataset->type == dns_rdatatype_nsec3 || 4806 1.1 christos rdataset->type == dns_rdatatype_rrsig) 4807 1.9 christos { 4808 1.23 christos return false; 4809 1.9 christos } 4810 1.1 christos 4811 1.1 christos /* 4812 1.1 christos * Look for a signature in a negative cache rdataset. 4813 1.1 christos */ 4814 1.9 christos if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0) { 4815 1.23 christos return true; 4816 1.9 christos } 4817 1.1 christos found = dns_fixedname_initname(&fixed); 4818 1.1 christos dns_rdataset_init(&trdataset); 4819 1.9 christos for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; 4820 1.9 christos result = dns_rdataset_next(rdataset)) 4821 1.9 christos { 4822 1.1 christos dns_ncache_current(rdataset, found, &trdataset); 4823 1.1 christos type = trdataset.type; 4824 1.1 christos dns_rdataset_disassociate(&trdataset); 4825 1.9 christos if (type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3 || 4826 1.1 christos type == dns_rdatatype_rrsig) 4827 1.9 christos { 4828 1.23 christos return false; 4829 1.9 christos } 4830 1.1 christos } 4831 1.23 christos return true; 4832 1.1 christos } 4833 1.1 christos 4834 1.1 christos /* 4835 1.1 christos * Extract a network address from the RDATA of an A or AAAA 4836 1.1 christos * record. 4837 1.1 christos * 4838 1.1 christos * Returns: 4839 1.1 christos * ISC_R_SUCCESS 4840 1.1 christos * ISC_R_NOTIMPLEMENTED The rdata is not a known address type. 4841 1.1 christos */ 4842 1.1 christos static isc_result_t 4843 1.1 christos rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) { 4844 1.1 christos struct in_addr ina; 4845 1.1 christos struct in6_addr in6a; 4846 1.1 christos 4847 1.1 christos switch (rdata->type) { 4848 1.1 christos case dns_rdatatype_a: 4849 1.1 christos INSIST(rdata->length == 4); 4850 1.1 christos memmove(&ina.s_addr, rdata->data, 4); 4851 1.1 christos isc_netaddr_fromin(netaddr, &ina); 4852 1.23 christos return ISC_R_SUCCESS; 4853 1.1 christos case dns_rdatatype_aaaa: 4854 1.1 christos INSIST(rdata->length == 16); 4855 1.1 christos memmove(in6a.s6_addr, rdata->data, 16); 4856 1.1 christos isc_netaddr_fromin6(netaddr, &in6a); 4857 1.23 christos return ISC_R_SUCCESS; 4858 1.1 christos default: 4859 1.23 christos return ISC_R_NOTIMPLEMENTED; 4860 1.1 christos } 4861 1.1 christos } 4862 1.1 christos 4863 1.1 christos static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 }; 4864 1.1 christos static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 }; 4865 1.1 christos static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 }; 4866 1.1 christos 4867 1.1 christos static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA"; 4868 1.1 christos 4869 1.1 christos static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA"; 4870 1.1 christos static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA"; 4871 1.1 christos static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA"; 4872 1.1 christos static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA"; 4873 1.1 christos static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA"; 4874 1.1 christos static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA"; 4875 1.1 christos static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA"; 4876 1.1 christos static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA"; 4877 1.1 christos static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA"; 4878 1.1 christos static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA"; 4879 1.1 christos static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA"; 4880 1.1 christos static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA"; 4881 1.1 christos static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA"; 4882 1.1 christos static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA"; 4883 1.1 christos static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA"; 4884 1.1 christos static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA"; 4885 1.1 christos 4886 1.1 christos static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA"; 4887 1.1 christos 4888 1.1 christos static dns_name_t rfc1918names[] = { 4889 1.1 christos DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets), 4890 1.1 christos DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets), 4891 1.1 christos DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets), 4892 1.1 christos DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets), 4893 1.1 christos DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets), 4894 1.1 christos DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets), 4895 1.1 christos DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets), 4896 1.1 christos DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets), 4897 1.1 christos DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets), 4898 1.1 christos DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets), 4899 1.1 christos DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets), 4900 1.1 christos DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets), 4901 1.1 christos DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets), 4902 1.1 christos DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets), 4903 1.1 christos DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets), 4904 1.1 christos DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets), 4905 1.1 christos DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets), 4906 1.1 christos DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets) 4907 1.1 christos }; 4908 1.1 christos 4909 1.1 christos static unsigned char prisoner_data[] = "\010prisoner\004iana\003org"; 4910 1.9 christos static unsigned char hostmaster_data[] = "\012hostmaster\014root-" 4911 1.9 christos "servers\003org"; 4912 1.1 christos 4913 1.1 christos static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 }; 4914 1.1 christos static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 }; 4915 1.1 christos 4916 1.9 christos static dns_name_t const prisoner = DNS_NAME_INITABSOLUTE(prisoner_data, 4917 1.9 christos prisoner_offsets); 4918 1.9 christos static dns_name_t const hostmaster = DNS_NAME_INITABSOLUTE(hostmaster_data, 4919 1.9 christos hostmaster_offsets); 4920 1.1 christos 4921 1.1 christos static void 4922 1.1 christos warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) { 4923 1.1 christos unsigned int i; 4924 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 4925 1.1 christos dns_rdata_soa_t soa; 4926 1.1 christos dns_rdataset_t found; 4927 1.1 christos isc_result_t result; 4928 1.1 christos 4929 1.9 christos for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) { 4930 1.1 christos if (dns_name_issubdomain(fname, &rfc1918names[i])) { 4931 1.1 christos dns_rdataset_init(&found); 4932 1.9 christos result = dns_ncache_getrdataset( 4933 1.9 christos rdataset, &rfc1918names[i], dns_rdatatype_soa, 4934 1.9 christos &found); 4935 1.9 christos if (result != ISC_R_SUCCESS) { 4936 1.1 christos return; 4937 1.9 christos } 4938 1.1 christos 4939 1.1 christos result = dns_rdataset_first(&found); 4940 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 4941 1.1 christos dns_rdataset_current(&found, &rdata); 4942 1.1 christos result = dns_rdata_tostruct(&rdata, &soa, NULL); 4943 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 4944 1.1 christos if (dns_name_equal(&soa.origin, &prisoner) && 4945 1.9 christos dns_name_equal(&soa.contact, &hostmaster)) 4946 1.9 christos { 4947 1.1 christos char buf[DNS_NAME_FORMATSIZE]; 4948 1.1 christos dns_name_format(fname, buf, sizeof(buf)); 4949 1.1 christos ns_client_log(client, DNS_LOGCATEGORY_SECURITY, 4950 1.1 christos NS_LOGMODULE_QUERY, 4951 1.1 christos ISC_LOG_WARNING, 4952 1.1 christos "RFC 1918 response from " 4953 1.9 christos "Internet for %s", 4954 1.9 christos buf); 4955 1.1 christos } 4956 1.1 christos dns_rdataset_disassociate(&found); 4957 1.1 christos return; 4958 1.1 christos } 4959 1.1 christos } 4960 1.1 christos } 4961 1.1 christos 4962 1.1 christos static void 4963 1.1 christos query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, 4964 1.1 christos dns_dbversion_t *version, ns_client_t *client, 4965 1.1 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 4966 1.9 christos dns_name_t *fname, bool exact, dns_name_t *found) { 4967 1.1 christos unsigned char salt[256]; 4968 1.1 christos size_t salt_length; 4969 1.3 christos uint16_t iterations; 4970 1.1 christos isc_result_t result; 4971 1.1 christos unsigned int dboptions; 4972 1.1 christos dns_fixedname_t fixed; 4973 1.1 christos dns_hash_t hash; 4974 1.1 christos dns_name_t name; 4975 1.1 christos unsigned int skip = 0, labels; 4976 1.1 christos dns_rdata_nsec3_t nsec3; 4977 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 4978 1.3 christos bool optout; 4979 1.1 christos dns_clientinfomethods_t cm; 4980 1.1 christos dns_clientinfo_t ci; 4981 1.1 christos 4982 1.1 christos salt_length = sizeof(salt); 4983 1.1 christos result = dns_db_getnsec3parameters(db, version, &hash, NULL, 4984 1.1 christos &iterations, salt, &salt_length); 4985 1.9 christos if (result != ISC_R_SUCCESS) { 4986 1.1 christos return; 4987 1.9 christos } 4988 1.1 christos 4989 1.1 christos dns_name_init(&name, NULL); 4990 1.1 christos dns_name_clone(qname, &name); 4991 1.1 christos labels = dns_name_countlabels(&name); 4992 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 4993 1.20 christos dns_clientinfo_init(&ci, client, NULL); 4994 1.1 christos 4995 1.1 christos /* 4996 1.1 christos * Map unknown algorithm to known value. 4997 1.1 christos */ 4998 1.9 christos if (hash == DNS_NSEC3_UNKNOWNALG) { 4999 1.1 christos hash = 1; 5000 1.9 christos } 5001 1.1 christos 5002 1.9 christos again: 5003 1.1 christos dns_fixedname_init(&fixed); 5004 1.1 christos result = dns_nsec3_hashname(&fixed, NULL, NULL, &name, 5005 1.9 christos dns_db_origin(db), hash, iterations, salt, 5006 1.9 christos salt_length); 5007 1.9 christos if (result != ISC_R_SUCCESS) { 5008 1.1 christos return; 5009 1.9 christos } 5010 1.1 christos 5011 1.1 christos dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3; 5012 1.1 christos result = dns_db_findext(db, dns_fixedname_name(&fixed), version, 5013 1.1 christos dns_rdatatype_nsec3, dboptions, client->now, 5014 1.1 christos NULL, fname, &cm, &ci, rdataset, sigrdataset); 5015 1.1 christos 5016 1.1 christos if (result == DNS_R_NXDOMAIN) { 5017 1.1 christos if (!dns_rdataset_isassociated(rdataset)) { 5018 1.1 christos return; 5019 1.1 christos } 5020 1.1 christos result = dns_rdataset_first(rdataset); 5021 1.1 christos INSIST(result == ISC_R_SUCCESS); 5022 1.1 christos dns_rdataset_current(rdataset, &rdata); 5023 1.3 christos result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 5024 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 5025 1.1 christos dns_rdata_reset(&rdata); 5026 1.3 christos optout = ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); 5027 1.1 christos if (found != NULL && optout && 5028 1.16 christos dns_name_issubdomain(&name, dns_db_origin(db))) 5029 1.16 christos { 5030 1.1 christos dns_rdataset_disassociate(rdataset); 5031 1.9 christos if (dns_rdataset_isassociated(sigrdataset)) { 5032 1.1 christos dns_rdataset_disassociate(sigrdataset); 5033 1.9 christos } 5034 1.1 christos skip++; 5035 1.1 christos dns_name_getlabelsequence(qname, skip, labels - skip, 5036 1.1 christos &name); 5037 1.1 christos ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, 5038 1.1 christos NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3), 5039 1.1 christos "looking for closest provable encloser"); 5040 1.1 christos goto again; 5041 1.1 christos } 5042 1.9 christos if (exact) { 5043 1.1 christos ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, 5044 1.1 christos NS_LOGMODULE_QUERY, ISC_LOG_WARNING, 5045 1.1 christos "expected a exact match NSEC3, got " 5046 1.1 christos "a covering record"); 5047 1.9 christos } 5048 1.1 christos } else if (result != ISC_R_SUCCESS) { 5049 1.1 christos return; 5050 1.9 christos } else if (!exact) { 5051 1.1 christos ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, 5052 1.1 christos NS_LOGMODULE_QUERY, ISC_LOG_WARNING, 5053 1.1 christos "expected covering NSEC3, got an exact match"); 5054 1.9 christos } 5055 1.1 christos if (found == qname) { 5056 1.9 christos if (skip != 0U) { 5057 1.1 christos dns_name_getlabelsequence(qname, skip, labels - skip, 5058 1.1 christos found); 5059 1.9 christos } 5060 1.9 christos } else if (found != NULL) { 5061 1.20 christos dns_name_copy(&name, found); 5062 1.9 christos } 5063 1.1 christos return; 5064 1.1 christos } 5065 1.1 christos 5066 1.3 christos static uint32_t 5067 1.1 christos dns64_ttl(dns_db_t *db, dns_dbversion_t *version) { 5068 1.1 christos dns_dbnode_t *node = NULL; 5069 1.1 christos dns_rdata_soa_t soa; 5070 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 5071 1.1 christos dns_rdataset_t rdataset; 5072 1.1 christos isc_result_t result; 5073 1.3 christos uint32_t ttl = UINT32_MAX; 5074 1.1 christos 5075 1.1 christos dns_rdataset_init(&rdataset); 5076 1.1 christos 5077 1.1 christos result = dns_db_getoriginnode(db, &node); 5078 1.9 christos if (result != ISC_R_SUCCESS) { 5079 1.1 christos goto cleanup; 5080 1.9 christos } 5081 1.1 christos 5082 1.9 christos result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, 0, 0, 5083 1.9 christos &rdataset, NULL); 5084 1.9 christos if (result != ISC_R_SUCCESS) { 5085 1.1 christos goto cleanup; 5086 1.9 christos } 5087 1.1 christos result = dns_rdataset_first(&rdataset); 5088 1.9 christos if (result != ISC_R_SUCCESS) { 5089 1.1 christos goto cleanup; 5090 1.9 christos } 5091 1.1 christos 5092 1.1 christos dns_rdataset_current(&rdataset, &rdata); 5093 1.1 christos result = dns_rdata_tostruct(&rdata, &soa, NULL); 5094 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 5095 1.1 christos ttl = ISC_MIN(rdataset.ttl, soa.minimum); 5096 1.1 christos 5097 1.1 christos cleanup: 5098 1.9 christos if (dns_rdataset_isassociated(&rdataset)) { 5099 1.1 christos dns_rdataset_disassociate(&rdataset); 5100 1.9 christos } 5101 1.9 christos if (node != NULL) { 5102 1.1 christos dns_db_detachnode(db, &node); 5103 1.9 christos } 5104 1.23 christos return ttl; 5105 1.1 christos } 5106 1.1 christos 5107 1.3 christos static bool 5108 1.1 christos dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset, 5109 1.9 christos dns_rdataset_t *sigrdataset) { 5110 1.1 christos isc_netaddr_t netaddr; 5111 1.20 christos dns_aclenv_t *env = client->manager->aclenv; 5112 1.1 christos dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64); 5113 1.1 christos unsigned int flags = 0; 5114 1.1 christos unsigned int i, count; 5115 1.3 christos bool *aaaaok; 5116 1.1 christos 5117 1.1 christos INSIST(client->query.dns64_aaaaok == NULL); 5118 1.1 christos INSIST(client->query.dns64_aaaaoklen == 0); 5119 1.1 christos INSIST(client->query.dns64_aaaa == NULL); 5120 1.1 christos INSIST(client->query.dns64_sigaaaa == NULL); 5121 1.1 christos 5122 1.9 christos if (dns64 == NULL) { 5123 1.23 christos return true; 5124 1.9 christos } 5125 1.1 christos 5126 1.9 christos if (RECURSIONOK(client)) { 5127 1.1 christos flags |= DNS_DNS64_RECURSIVE; 5128 1.9 christos } 5129 1.1 christos 5130 1.1 christos if (WANTDNSSEC(client) && sigrdataset != NULL && 5131 1.1 christos dns_rdataset_isassociated(sigrdataset)) 5132 1.9 christos { 5133 1.1 christos flags |= DNS_DNS64_DNSSEC; 5134 1.9 christos } 5135 1.1 christos 5136 1.1 christos count = dns_rdataset_count(rdataset); 5137 1.23 christos aaaaok = isc_mem_cget(client->manager->mctx, count, sizeof(bool)); 5138 1.1 christos 5139 1.1 christos isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); 5140 1.9 christos if (dns_dns64_aaaaok(dns64, &netaddr, client->signer, env, flags, 5141 1.9 christos rdataset, aaaaok, count)) 5142 1.1 christos { 5143 1.1 christos for (i = 0; i < count; i++) { 5144 1.1 christos if (aaaaok != NULL && !aaaaok[i]) { 5145 1.1 christos SAVE(client->query.dns64_aaaaok, aaaaok); 5146 1.1 christos client->query.dns64_aaaaoklen = count; 5147 1.1 christos break; 5148 1.1 christos } 5149 1.1 christos } 5150 1.9 christos if (aaaaok != NULL) { 5151 1.23 christos isc_mem_cput(client->manager->mctx, aaaaok, count, 5152 1.23 christos sizeof(bool)); 5153 1.9 christos } 5154 1.23 christos return true; 5155 1.1 christos } 5156 1.9 christos if (aaaaok != NULL) { 5157 1.23 christos isc_mem_cput(client->manager->mctx, aaaaok, count, 5158 1.23 christos sizeof(bool)); 5159 1.9 christos } 5160 1.23 christos return false; 5161 1.1 christos } 5162 1.1 christos 5163 1.1 christos /* 5164 1.1 christos * Look for the name and type in the redirection zone. If found update 5165 1.3 christos * the arguments as appropriate. Return true if a update was 5166 1.1 christos * performed. 5167 1.1 christos * 5168 1.1 christos * Only perform the update if the client is in the allow query acl and 5169 1.1 christos * returning the update would not cause a DNSSEC validation failure. 5170 1.1 christos */ 5171 1.1 christos static isc_result_t 5172 1.1 christos redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset, 5173 1.1 christos dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp, 5174 1.9 christos dns_rdatatype_t qtype) { 5175 1.1 christos dns_db_t *db = NULL; 5176 1.1 christos dns_dbnode_t *node = NULL; 5177 1.1 christos dns_fixedname_t fixed; 5178 1.1 christos dns_name_t *found; 5179 1.1 christos dns_rdataset_t trdataset; 5180 1.1 christos isc_result_t result; 5181 1.1 christos dns_rdatatype_t type; 5182 1.1 christos dns_clientinfomethods_t cm; 5183 1.1 christos dns_clientinfo_t ci; 5184 1.1 christos ns_dbversion_t *dbversion; 5185 1.1 christos 5186 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "redirect"); 5187 1.1 christos 5188 1.9 christos if (client->view->redirect == NULL) { 5189 1.23 christos return ISC_R_NOTFOUND; 5190 1.9 christos } 5191 1.1 christos 5192 1.1 christos found = dns_fixedname_initname(&fixed); 5193 1.1 christos dns_rdataset_init(&trdataset); 5194 1.1 christos 5195 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 5196 1.20 christos dns_clientinfo_init(&ci, client, NULL); 5197 1.20 christos dns_clientinfo_setecs(&ci, &client->ecs); 5198 1.1 christos 5199 1.1 christos if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp)) 5200 1.9 christos { 5201 1.23 christos return ISC_R_NOTFOUND; 5202 1.9 christos } 5203 1.1 christos 5204 1.1 christos if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) { 5205 1.9 christos if (rdataset->trust == dns_trust_secure) { 5206 1.23 christos return ISC_R_NOTFOUND; 5207 1.9 christos } 5208 1.1 christos if (rdataset->trust == dns_trust_ultimate && 5209 1.1 christos (rdataset->type == dns_rdatatype_nsec || 5210 1.1 christos rdataset->type == dns_rdatatype_nsec3)) 5211 1.9 christos { 5212 1.23 christos return ISC_R_NOTFOUND; 5213 1.9 christos } 5214 1.1 christos if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { 5215 1.1 christos for (result = dns_rdataset_first(rdataset); 5216 1.1 christos result == ISC_R_SUCCESS; 5217 1.9 christos result = dns_rdataset_next(rdataset)) 5218 1.9 christos { 5219 1.1 christos dns_ncache_current(rdataset, found, &trdataset); 5220 1.1 christos type = trdataset.type; 5221 1.1 christos dns_rdataset_disassociate(&trdataset); 5222 1.1 christos if (type == dns_rdatatype_nsec || 5223 1.1 christos type == dns_rdatatype_nsec3 || 5224 1.1 christos type == dns_rdatatype_rrsig) 5225 1.9 christos { 5226 1.23 christos return ISC_R_NOTFOUND; 5227 1.9 christos } 5228 1.1 christos } 5229 1.1 christos } 5230 1.1 christos } 5231 1.1 christos 5232 1.9 christos result = ns_client_checkaclsilent( 5233 1.9 christos client, NULL, dns_zone_getqueryacl(client->view->redirect), 5234 1.9 christos true); 5235 1.9 christos if (result != ISC_R_SUCCESS) { 5236 1.23 christos return ISC_R_NOTFOUND; 5237 1.9 christos } 5238 1.1 christos 5239 1.1 christos result = dns_zone_getdb(client->view->redirect, &db); 5240 1.9 christos if (result != ISC_R_SUCCESS) { 5241 1.23 christos return ISC_R_NOTFOUND; 5242 1.9 christos } 5243 1.1 christos 5244 1.3 christos dbversion = ns_client_findversion(client, db); 5245 1.1 christos if (dbversion == NULL) { 5246 1.1 christos dns_db_detach(&db); 5247 1.23 christos return ISC_R_NOTFOUND; 5248 1.1 christos } 5249 1.1 christos 5250 1.1 christos /* 5251 1.1 christos * Lookup the requested data in the redirect zone. 5252 1.1 christos */ 5253 1.1 christos result = dns_db_findext(db, client->query.qname, dbversion->version, 5254 1.9 christos qtype, DNS_DBFIND_NOZONECUT, client->now, &node, 5255 1.9 christos found, &cm, &ci, &trdataset, NULL); 5256 1.1 christos if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) { 5257 1.9 christos if (dns_rdataset_isassociated(rdataset)) { 5258 1.1 christos dns_rdataset_disassociate(rdataset); 5259 1.9 christos } 5260 1.9 christos if (dns_rdataset_isassociated(&trdataset)) { 5261 1.1 christos dns_rdataset_disassociate(&trdataset); 5262 1.9 christos } 5263 1.1 christos goto nxrrset; 5264 1.1 christos } else if (result != ISC_R_SUCCESS) { 5265 1.9 christos if (dns_rdataset_isassociated(&trdataset)) { 5266 1.1 christos dns_rdataset_disassociate(&trdataset); 5267 1.9 christos } 5268 1.9 christos if (node != NULL) { 5269 1.1 christos dns_db_detachnode(db, &node); 5270 1.9 christos } 5271 1.1 christos dns_db_detach(&db); 5272 1.23 christos return ISC_R_NOTFOUND; 5273 1.1 christos } 5274 1.1 christos 5275 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done"); 5276 1.20 christos dns_name_copy(found, name); 5277 1.9 christos if (dns_rdataset_isassociated(rdataset)) { 5278 1.1 christos dns_rdataset_disassociate(rdataset); 5279 1.9 christos } 5280 1.1 christos if (dns_rdataset_isassociated(&trdataset)) { 5281 1.1 christos dns_rdataset_clone(&trdataset, rdataset); 5282 1.1 christos dns_rdataset_disassociate(&trdataset); 5283 1.1 christos } 5284 1.9 christos nxrrset: 5285 1.9 christos if (*nodep != NULL) { 5286 1.1 christos dns_db_detachnode(*dbp, nodep); 5287 1.9 christos } 5288 1.1 christos dns_db_detach(dbp); 5289 1.1 christos dns_db_attachnode(db, node, nodep); 5290 1.1 christos dns_db_attach(db, dbp); 5291 1.1 christos dns_db_detachnode(db, &node); 5292 1.1 christos dns_db_detach(&db); 5293 1.1 christos *versionp = dbversion->version; 5294 1.1 christos 5295 1.1 christos client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 5296 1.1 christos NS_QUERYATTR_NOADDITIONAL); 5297 1.1 christos 5298 1.23 christos return result; 5299 1.1 christos } 5300 1.1 christos 5301 1.1 christos static isc_result_t 5302 1.1 christos redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset, 5303 1.1 christos dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp, 5304 1.9 christos dns_rdatatype_t qtype, bool *is_zonep) { 5305 1.1 christos dns_db_t *db = NULL; 5306 1.1 christos dns_dbnode_t *node = NULL; 5307 1.1 christos dns_fixedname_t fixed; 5308 1.1 christos dns_fixedname_t fixedredirect; 5309 1.1 christos dns_name_t *found, *redirectname; 5310 1.1 christos dns_rdataset_t trdataset; 5311 1.1 christos isc_result_t result; 5312 1.1 christos dns_rdatatype_t type; 5313 1.1 christos dns_clientinfomethods_t cm; 5314 1.1 christos dns_clientinfo_t ci; 5315 1.1 christos dns_dbversion_t *version = NULL; 5316 1.1 christos dns_zone_t *zone = NULL; 5317 1.3 christos bool is_zone; 5318 1.5 christos unsigned int labels; 5319 1.1 christos 5320 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "redirect2"); 5321 1.1 christos 5322 1.5 christos if (client->view->redirectzone == NULL) { 5323 1.23 christos return ISC_R_NOTFOUND; 5324 1.5 christos } 5325 1.1 christos 5326 1.5 christos if (dns_name_issubdomain(name, client->view->redirectzone)) { 5327 1.23 christos return ISC_R_NOTFOUND; 5328 1.5 christos } 5329 1.1 christos 5330 1.1 christos found = dns_fixedname_initname(&fixed); 5331 1.1 christos dns_rdataset_init(&trdataset); 5332 1.1 christos 5333 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 5334 1.20 christos dns_clientinfo_init(&ci, client, NULL); 5335 1.20 christos dns_clientinfo_setecs(&ci, &client->ecs); 5336 1.1 christos 5337 1.9 christos if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp)) 5338 1.9 christos { 5339 1.23 christos return ISC_R_NOTFOUND; 5340 1.5 christos } 5341 1.1 christos 5342 1.1 christos if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) { 5343 1.9 christos if (rdataset->trust == dns_trust_secure) { 5344 1.23 christos return ISC_R_NOTFOUND; 5345 1.9 christos } 5346 1.1 christos if (rdataset->trust == dns_trust_ultimate && 5347 1.1 christos (rdataset->type == dns_rdatatype_nsec || 5348 1.1 christos rdataset->type == dns_rdatatype_nsec3)) 5349 1.9 christos { 5350 1.23 christos return ISC_R_NOTFOUND; 5351 1.9 christos } 5352 1.1 christos if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { 5353 1.1 christos for (result = dns_rdataset_first(rdataset); 5354 1.1 christos result == ISC_R_SUCCESS; 5355 1.9 christos result = dns_rdataset_next(rdataset)) 5356 1.9 christos { 5357 1.1 christos dns_ncache_current(rdataset, found, &trdataset); 5358 1.1 christos type = trdataset.type; 5359 1.1 christos dns_rdataset_disassociate(&trdataset); 5360 1.1 christos if (type == dns_rdatatype_nsec || 5361 1.1 christos type == dns_rdatatype_nsec3 || 5362 1.1 christos type == dns_rdatatype_rrsig) 5363 1.9 christos { 5364 1.23 christos return ISC_R_NOTFOUND; 5365 1.9 christos } 5366 1.1 christos } 5367 1.1 christos } 5368 1.1 christos } 5369 1.1 christos 5370 1.1 christos redirectname = dns_fixedname_initname(&fixedredirect); 5371 1.5 christos labels = dns_name_countlabels(client->query.qname); 5372 1.5 christos if (labels > 1U) { 5373 1.1 christos dns_name_t prefix; 5374 1.1 christos 5375 1.1 christos dns_name_init(&prefix, NULL); 5376 1.5 christos dns_name_getlabelsequence(client->query.qname, 0, labels - 1, 5377 1.5 christos &prefix); 5378 1.1 christos result = dns_name_concatenate(&prefix, 5379 1.1 christos client->view->redirectzone, 5380 1.1 christos redirectname, NULL); 5381 1.9 christos if (result != ISC_R_SUCCESS) { 5382 1.23 christos return ISC_R_NOTFOUND; 5383 1.9 christos } 5384 1.5 christos } else { 5385 1.20 christos dns_name_copy(redirectname, client->view->redirectzone); 5386 1.5 christos } 5387 1.1 christos 5388 1.23 christos result = query_getdb(client, redirectname, qtype, 5389 1.23 christos (dns_getdb_options_t){ 0 }, &zone, &db, &version, 5390 1.23 christos &is_zone); 5391 1.5 christos if (result != ISC_R_SUCCESS) { 5392 1.23 christos return ISC_R_NOTFOUND; 5393 1.5 christos } 5394 1.5 christos if (zone != NULL) { 5395 1.1 christos dns_zone_detach(&zone); 5396 1.5 christos } 5397 1.1 christos 5398 1.1 christos /* 5399 1.1 christos * Lookup the requested data in the redirect zone. 5400 1.1 christos */ 5401 1.9 christos result = dns_db_findext(db, redirectname, version, qtype, 0, 5402 1.9 christos client->now, &node, found, &cm, &ci, &trdataset, 5403 1.9 christos NULL); 5404 1.1 christos if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) { 5405 1.9 christos if (dns_rdataset_isassociated(rdataset)) { 5406 1.1 christos dns_rdataset_disassociate(rdataset); 5407 1.9 christos } 5408 1.9 christos if (dns_rdataset_isassociated(&trdataset)) { 5409 1.1 christos dns_rdataset_disassociate(&trdataset); 5410 1.9 christos } 5411 1.1 christos goto nxrrset; 5412 1.1 christos } else if (result == ISC_R_NOTFOUND || result == DNS_R_DELEGATION) { 5413 1.1 christos /* 5414 1.1 christos * Cleanup. 5415 1.1 christos */ 5416 1.9 christos if (dns_rdataset_isassociated(&trdataset)) { 5417 1.1 christos dns_rdataset_disassociate(&trdataset); 5418 1.9 christos } 5419 1.9 christos if (node != NULL) { 5420 1.1 christos dns_db_detachnode(db, &node); 5421 1.9 christos } 5422 1.1 christos dns_db_detach(&db); 5423 1.1 christos /* 5424 1.1 christos * Don't loop forever if the lookup failed last time. 5425 1.1 christos */ 5426 1.1 christos if (!REDIRECT(client)) { 5427 1.3 christos result = ns_query_recurse(client, qtype, redirectname, 5428 1.3 christos NULL, NULL, true); 5429 1.1 christos if (result == ISC_R_SUCCESS) { 5430 1.1 christos client->query.attributes |= 5431 1.9 christos NS_QUERYATTR_RECURSING; 5432 1.1 christos client->query.attributes |= 5433 1.9 christos NS_QUERYATTR_REDIRECT; 5434 1.23 christos return DNS_R_CONTINUE; 5435 1.1 christos } 5436 1.1 christos } 5437 1.23 christos return ISC_R_NOTFOUND; 5438 1.1 christos } else if (result != ISC_R_SUCCESS) { 5439 1.9 christos if (dns_rdataset_isassociated(&trdataset)) { 5440 1.1 christos dns_rdataset_disassociate(&trdataset); 5441 1.9 christos } 5442 1.9 christos if (node != NULL) { 5443 1.1 christos dns_db_detachnode(db, &node); 5444 1.9 christos } 5445 1.1 christos dns_db_detach(&db); 5446 1.23 christos return ISC_R_NOTFOUND; 5447 1.1 christos } 5448 1.1 christos 5449 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "redirect2: found data: done"); 5450 1.1 christos /* 5451 1.1 christos * Adjust the found name to not include the redirectzone suffix. 5452 1.1 christos */ 5453 1.1 christos dns_name_split(found, dns_name_countlabels(client->view->redirectzone), 5454 1.1 christos found, NULL); 5455 1.1 christos /* 5456 1.1 christos * Make the name absolute. 5457 1.1 christos */ 5458 1.1 christos result = dns_name_concatenate(found, dns_rootname, found, NULL); 5459 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 5460 1.1 christos 5461 1.20 christos dns_name_copy(found, name); 5462 1.9 christos if (dns_rdataset_isassociated(rdataset)) { 5463 1.1 christos dns_rdataset_disassociate(rdataset); 5464 1.9 christos } 5465 1.1 christos if (dns_rdataset_isassociated(&trdataset)) { 5466 1.1 christos dns_rdataset_clone(&trdataset, rdataset); 5467 1.1 christos dns_rdataset_disassociate(&trdataset); 5468 1.1 christos } 5469 1.9 christos nxrrset: 5470 1.9 christos if (*nodep != NULL) { 5471 1.1 christos dns_db_detachnode(*dbp, nodep); 5472 1.9 christos } 5473 1.1 christos dns_db_detach(dbp); 5474 1.1 christos dns_db_attachnode(db, node, nodep); 5475 1.1 christos dns_db_attach(db, dbp); 5476 1.1 christos dns_db_detachnode(db, &node); 5477 1.1 christos dns_db_detach(&db); 5478 1.1 christos *is_zonep = is_zone; 5479 1.1 christos *versionp = version; 5480 1.1 christos 5481 1.1 christos client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 5482 1.1 christos NS_QUERYATTR_NOADDITIONAL); 5483 1.1 christos 5484 1.23 christos return result; 5485 1.1 christos } 5486 1.1 christos 5487 1.1 christos /*% 5488 1.1 christos * Initialize query context 'qctx'. Run by query_setup() when 5489 1.1 christos * first handling a client query, and by query_resume() when 5490 1.1 christos * returning from recursion. 5491 1.3 christos * 5492 1.3 christos * Whenever this function is called, qctx_destroy() must be called 5493 1.3 christos * when leaving the scope or freeing the qctx. 5494 1.1 christos */ 5495 1.1 christos static void 5496 1.23 christos qctx_init(ns_client_t *client, dns_fetchresponse_t **frespp, 5497 1.23 christos dns_rdatatype_t qtype, query_ctx_t *qctx) { 5498 1.1 christos REQUIRE(qctx != NULL); 5499 1.1 christos REQUIRE(client != NULL); 5500 1.1 christos 5501 1.3 christos memset(qctx, 0, sizeof(*qctx)); 5502 1.3 christos 5503 1.1 christos /* Set this first so CCTRACE will work */ 5504 1.1 christos qctx->client = client; 5505 1.9 christos 5506 1.3 christos dns_view_attach(client->view, &qctx->view); 5507 1.1 christos 5508 1.3 christos CCTRACE(ISC_LOG_DEBUG(3), "qctx_init"); 5509 1.1 christos 5510 1.23 christos if (frespp != NULL) { 5511 1.23 christos qctx->fresp = *frespp; 5512 1.23 christos *frespp = NULL; 5513 1.11 christos } else { 5514 1.23 christos qctx->fresp = NULL; 5515 1.11 christos } 5516 1.1 christos qctx->qtype = qctx->type = qtype; 5517 1.1 christos qctx->result = ISC_R_SUCCESS; 5518 1.3 christos qctx->findcoveringnsec = qctx->view->synthfromdnssec; 5519 1.3 christos 5520 1.16 christos /* 5521 1.16 christos * If it's an RRSIG or SIG query, we'll iterate the node. 5522 1.16 christos */ 5523 1.16 christos if (qctx->qtype == dns_rdatatype_rrsig || 5524 1.16 christos qctx->qtype == dns_rdatatype_sig) 5525 1.16 christos { 5526 1.16 christos qctx->type = dns_rdatatype_any; 5527 1.16 christos } 5528 1.16 christos 5529 1.3 christos CALL_HOOK_NORETURN(NS_QUERY_QCTX_INITIALIZED, qctx); 5530 1.1 christos } 5531 1.1 christos 5532 1.1 christos /*% 5533 1.1 christos * Clean up and disassociate the rdataset and node pointers in qctx. 5534 1.1 christos */ 5535 1.1 christos static void 5536 1.1 christos qctx_clean(query_ctx_t *qctx) { 5537 1.9 christos if (qctx->rdataset != NULL && dns_rdataset_isassociated(qctx->rdataset)) 5538 1.1 christos { 5539 1.1 christos dns_rdataset_disassociate(qctx->rdataset); 5540 1.1 christos } 5541 1.1 christos if (qctx->sigrdataset != NULL && 5542 1.16 christos dns_rdataset_isassociated(qctx->sigrdataset)) 5543 1.16 christos { 5544 1.1 christos dns_rdataset_disassociate(qctx->sigrdataset); 5545 1.1 christos } 5546 1.1 christos if (qctx->db != NULL && qctx->node != NULL) { 5547 1.1 christos dns_db_detachnode(qctx->db, &qctx->node); 5548 1.1 christos } 5549 1.24 christos if (qctx->client != NULL && qctx->client->query.gluedb != NULL) { 5550 1.24 christos dns_db_detach(&qctx->client->query.gluedb); 5551 1.24 christos } 5552 1.1 christos } 5553 1.1 christos 5554 1.1 christos /*% 5555 1.1 christos * Free any allocated memory associated with qctx. 5556 1.1 christos */ 5557 1.1 christos static void 5558 1.1 christos qctx_freedata(query_ctx_t *qctx) { 5559 1.1 christos if (qctx->rdataset != NULL) { 5560 1.3 christos ns_client_putrdataset(qctx->client, &qctx->rdataset); 5561 1.1 christos } 5562 1.1 christos 5563 1.1 christos if (qctx->sigrdataset != NULL) { 5564 1.3 christos ns_client_putrdataset(qctx->client, &qctx->sigrdataset); 5565 1.1 christos } 5566 1.1 christos 5567 1.1 christos if (qctx->fname != NULL) { 5568 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 5569 1.1 christos } 5570 1.1 christos 5571 1.1 christos if (qctx->db != NULL) { 5572 1.1 christos INSIST(qctx->node == NULL); 5573 1.1 christos dns_db_detach(&qctx->db); 5574 1.1 christos } 5575 1.1 christos 5576 1.1 christos if (qctx->zone != NULL) { 5577 1.1 christos dns_zone_detach(&qctx->zone); 5578 1.1 christos } 5579 1.1 christos 5580 1.1 christos if (qctx->zdb != NULL) { 5581 1.3 christos ns_client_putrdataset(qctx->client, &qctx->zsigrdataset); 5582 1.3 christos ns_client_putrdataset(qctx->client, &qctx->zrdataset); 5583 1.3 christos ns_client_releasename(qctx->client, &qctx->zfname); 5584 1.3 christos dns_db_detachnode(qctx->zdb, &qctx->znode); 5585 1.1 christos dns_db_detach(&qctx->zdb); 5586 1.22 christos qctx->zversion = NULL; 5587 1.1 christos } 5588 1.1 christos 5589 1.23 christos if (qctx->fresp != NULL) { 5590 1.23 christos free_fresp(qctx->client, &qctx->fresp); 5591 1.1 christos } 5592 1.1 christos } 5593 1.1 christos 5594 1.3 christos static void 5595 1.3 christos qctx_destroy(query_ctx_t *qctx) { 5596 1.3 christos CALL_HOOK_NORETURN(NS_QUERY_QCTX_DESTROYED, qctx); 5597 1.3 christos 5598 1.3 christos dns_view_detach(&qctx->view); 5599 1.3 christos } 5600 1.3 christos 5601 1.20 christos /* 5602 1.20 christos * Call SAVE but set 'a' to NULL first so as not to assert. 5603 1.20 christos */ 5604 1.20 christos #define INITANDSAVE(a, b) \ 5605 1.20 christos do { \ 5606 1.20 christos a = NULL; \ 5607 1.20 christos SAVE(a, b); \ 5608 1.20 christos } while (0) 5609 1.20 christos 5610 1.20 christos /* 5611 1.20 christos * "save" qctx data from 'src' to 'tgt'. 5612 1.20 christos * It essentially moves ownership of the data from src to tgt, so the former 5613 1.20 christos * becomes unusable except for final cleanup (such as by qctx_destroy). 5614 1.20 christos * Note: this function doesn't attach to the client's handle. It's the caller's 5615 1.20 christos * responsibility to do it if it's necessary. 5616 1.20 christos */ 5617 1.20 christos static void 5618 1.20 christos qctx_save(query_ctx_t *src, query_ctx_t *tgt) { 5619 1.20 christos /* First copy all fields in a straightforward way */ 5620 1.20 christos *tgt = *src; 5621 1.20 christos 5622 1.20 christos /* Then "move" pointers (except client and view) */ 5623 1.20 christos INITANDSAVE(tgt->dbuf, src->dbuf); 5624 1.20 christos INITANDSAVE(tgt->fname, src->fname); 5625 1.20 christos INITANDSAVE(tgt->tname, src->tname); 5626 1.20 christos INITANDSAVE(tgt->rdataset, src->rdataset); 5627 1.20 christos INITANDSAVE(tgt->sigrdataset, src->sigrdataset); 5628 1.20 christos INITANDSAVE(tgt->noqname, src->noqname); 5629 1.23 christos INITANDSAVE(tgt->fresp, src->fresp); 5630 1.20 christos INITANDSAVE(tgt->db, src->db); 5631 1.20 christos INITANDSAVE(tgt->version, src->version); 5632 1.20 christos INITANDSAVE(tgt->node, src->node); 5633 1.20 christos INITANDSAVE(tgt->zdb, src->zdb); 5634 1.20 christos INITANDSAVE(tgt->znode, src->znode); 5635 1.20 christos INITANDSAVE(tgt->zfname, src->zfname); 5636 1.20 christos INITANDSAVE(tgt->zversion, src->zversion); 5637 1.20 christos INITANDSAVE(tgt->zrdataset, src->zrdataset); 5638 1.20 christos INITANDSAVE(tgt->zsigrdataset, src->zsigrdataset); 5639 1.20 christos INITANDSAVE(tgt->rpz_st, src->rpz_st); 5640 1.20 christos INITANDSAVE(tgt->zone, src->zone); 5641 1.20 christos 5642 1.20 christos /* View has to stay in 'src' for qctx_destroy. */ 5643 1.20 christos tgt->view = NULL; 5644 1.20 christos dns_view_attach(src->view, &tgt->view); 5645 1.20 christos } 5646 1.20 christos 5647 1.1 christos /*% 5648 1.1 christos * Log detailed information about the query immediately after 5649 1.1 christos * the client request or a return from recursion. 5650 1.1 christos */ 5651 1.1 christos static void 5652 1.1 christos query_trace(query_ctx_t *qctx) { 5653 1.1 christos #ifdef WANT_QUERYTRACE 5654 1.6 christos char mbuf[2 * DNS_NAME_FORMATSIZE]; 5655 1.1 christos char qbuf[DNS_NAME_FORMATSIZE]; 5656 1.1 christos 5657 1.9 christos if (qctx->client->query.origqname != NULL) { 5658 1.1 christos dns_name_format(qctx->client->query.origqname, qbuf, 5659 1.1 christos sizeof(qbuf)); 5660 1.9 christos } else { 5661 1.1 christos snprintf(qbuf, sizeof(qbuf), "<unset>"); 5662 1.9 christos } 5663 1.1 christos 5664 1.1 christos snprintf(mbuf, sizeof(mbuf) - 1, 5665 1.1 christos "client attr:0x%x, query attr:0x%X, restarts:%u, " 5666 1.1 christos "origqname:%s, timer:%d, authdb:%d, referral:%d", 5667 1.9 christos qctx->client->attributes, qctx->client->query.attributes, 5668 1.1 christos qctx->client->query.restarts, qbuf, 5669 1.9 christos (int)qctx->client->query.timerset, 5670 1.9 christos (int)qctx->client->query.authdbset, 5671 1.9 christos (int)qctx->client->query.isreferral); 5672 1.1 christos CCTRACE(ISC_LOG_DEBUG(3), mbuf); 5673 1.9 christos #else /* ifdef WANT_QUERYTRACE */ 5674 1.1 christos UNUSED(qctx); 5675 1.9 christos #endif /* ifdef WANT_QUERYTRACE */ 5676 1.1 christos } 5677 1.1 christos 5678 1.1 christos /* 5679 1.1 christos * Set up query processing for the current query of 'client'. 5680 1.1 christos * Calls qctx_init() to initialize a query context, checks 5681 1.1 christos * the SERVFAIL cache, then hands off processing to ns__query_start(). 5682 1.1 christos * 5683 1.1 christos * This is called only from ns_query_start(), to begin a query 5684 1.1 christos * for the first time. Restarting an existing query (for 5685 1.1 christos * instance, to handle CNAME lookups), is done by calling 5686 1.1 christos * ns__query_start() again with the same query context. Resuming from 5687 1.1 christos * recursion is handled by query_resume(). 5688 1.1 christos */ 5689 1.23 christos static void 5690 1.1 christos query_setup(ns_client_t *client, dns_rdatatype_t qtype) { 5691 1.20 christos isc_result_t result = ISC_R_UNSET; 5692 1.1 christos query_ctx_t qctx; 5693 1.1 christos 5694 1.1 christos qctx_init(client, NULL, qtype, &qctx); 5695 1.1 christos query_trace(&qctx); 5696 1.1 christos 5697 1.3 christos CALL_HOOK(NS_QUERY_SETUP, &qctx); 5698 1.3 christos 5699 1.1 christos /* 5700 1.1 christos * Check SERVFAIL cache 5701 1.1 christos */ 5702 1.1 christos result = ns__query_sfcache(&qctx); 5703 1.1 christos if (result != ISC_R_COMPLETE) { 5704 1.23 christos goto cleanup; 5705 1.1 christos } 5706 1.1 christos 5707 1.23 christos (void)ns__query_start(&qctx); 5708 1.3 christos 5709 1.9 christos cleanup: 5710 1.3 christos qctx_destroy(&qctx); 5711 1.1 christos } 5712 1.1 christos 5713 1.3 christos static bool 5714 1.1 christos get_root_key_sentinel_id(query_ctx_t *qctx, const char *ndata) { 5715 1.1 christos unsigned int v = 0; 5716 1.1 christos int i; 5717 1.1 christos 5718 1.1 christos for (i = 0; i < 5; i++) { 5719 1.14 christos if (!isdigit((unsigned char)ndata[i])) { 5720 1.23 christos return false; 5721 1.1 christos } 5722 1.1 christos v *= 10; 5723 1.1 christos v += ndata[i] - '0'; 5724 1.1 christos } 5725 1.1 christos if (v > 65535U) { 5726 1.23 christos return false; 5727 1.1 christos } 5728 1.1 christos qctx->client->query.root_key_sentinel_keyid = v; 5729 1.23 christos return true; 5730 1.1 christos } 5731 1.1 christos 5732 1.1 christos /*% 5733 1.1 christos * Find out if the query is for a root key sentinel and if so, record the type 5734 1.1 christos * of root key sentinel query and the key id that is being checked for. 5735 1.1 christos * 5736 1.1 christos * The code is assuming a zero padded decimal field of width 5. 5737 1.1 christos */ 5738 1.1 christos static void 5739 1.1 christos root_key_sentinel_detect(query_ctx_t *qctx) { 5740 1.1 christos const char *ndata = (const char *)qctx->client->query.qname->ndata; 5741 1.1 christos 5742 1.1 christos if (qctx->client->query.qname->length > 30 && ndata[0] == 29 && 5743 1.1 christos strncasecmp(ndata + 1, "root-key-sentinel-is-ta-", 24) == 0) 5744 1.1 christos { 5745 1.1 christos if (!get_root_key_sentinel_id(qctx, ndata + 25)) { 5746 1.1 christos return; 5747 1.1 christos } 5748 1.3 christos qctx->client->query.root_key_sentinel_is_ta = true; 5749 1.1 christos /* 5750 1.9 christos * Simplify processing by disabling aggressive 5751 1.1 christos * negative caching. 5752 1.1 christos */ 5753 1.3 christos qctx->findcoveringnsec = false; 5754 1.1 christos ns_client_log(qctx->client, NS_LOGCATEGORY_TAT, 5755 1.1 christos NS_LOGMODULE_QUERY, ISC_LOG_INFO, 5756 1.1 christos "root-key-sentinel-is-ta query label found"); 5757 1.1 christos } else if (qctx->client->query.qname->length > 31 && ndata[0] == 30 && 5758 1.1 christos strncasecmp(ndata + 1, "root-key-sentinel-not-ta-", 25) == 0) 5759 1.1 christos { 5760 1.1 christos if (!get_root_key_sentinel_id(qctx, ndata + 26)) { 5761 1.1 christos return; 5762 1.1 christos } 5763 1.3 christos qctx->client->query.root_key_sentinel_not_ta = true; 5764 1.1 christos /* 5765 1.9 christos * Simplify processing by disabling aggressive 5766 1.1 christos * negative caching. 5767 1.1 christos */ 5768 1.3 christos qctx->findcoveringnsec = false; 5769 1.1 christos ns_client_log(qctx->client, NS_LOGCATEGORY_TAT, 5770 1.1 christos NS_LOGMODULE_QUERY, ISC_LOG_INFO, 5771 1.1 christos "root-key-sentinel-not-ta query label found"); 5772 1.1 christos } 5773 1.1 christos } 5774 1.1 christos 5775 1.1 christos /*% 5776 1.1 christos * Starting point for a client query or a chaining query. 5777 1.1 christos * 5778 1.1 christos * Called first by query_setup(), and then again as often as needed to 5779 1.1 christos * follow a CNAME chain. Determines which authoritative database to 5780 1.1 christos * search, then hands off processing to query_lookup(). 5781 1.1 christos */ 5782 1.1 christos isc_result_t 5783 1.1 christos ns__query_start(query_ctx_t *qctx) { 5784 1.20 christos isc_result_t result = ISC_R_UNSET; 5785 1.1 christos CCTRACE(ISC_LOG_DEBUG(3), "ns__query_start"); 5786 1.3 christos qctx->want_restart = false; 5787 1.3 christos qctx->authoritative = false; 5788 1.1 christos qctx->version = NULL; 5789 1.1 christos qctx->zversion = NULL; 5790 1.3 christos qctx->need_wildcardproof = false; 5791 1.3 christos qctx->rpz = false; 5792 1.3 christos 5793 1.3 christos CALL_HOOK(NS_QUERY_START_BEGIN, qctx); 5794 1.3 christos 5795 1.3 christos /* 5796 1.23 christos * If we require a server cookie or the presented server 5797 1.23 christos * cookie was bad then send back BADCOOKIE before we have 5798 1.23 christos * done too much work. 5799 1.23 christos */ 5800 1.23 christos if (!TCP(qctx->client) && 5801 1.23 christos (BADCOOKIE(qctx->client) || 5802 1.23 christos (qctx->view->requireservercookie && WANTCOOKIE(qctx->client) && 5803 1.23 christos !HAVECOOKIE(qctx->client)))) 5804 1.3 christos { 5805 1.3 christos qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA; 5806 1.3 christos qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD; 5807 1.3 christos qctx->client->message->rcode = dns_rcode_badcookie; 5808 1.23 christos return ns_query_done(qctx); 5809 1.3 christos } 5810 1.1 christos 5811 1.3 christos if (qctx->view->checknames && 5812 1.1 christos !dns_rdata_checkowner(qctx->client->query.qname, 5813 1.9 christos qctx->client->message->rdclass, qctx->qtype, 5814 1.9 christos false)) 5815 1.1 christos { 5816 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 5817 1.3 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 5818 1.3 christos char classbuf[DNS_RDATACLASS_FORMATSIZE]; 5819 1.1 christos 5820 1.9 christos dns_name_format(qctx->client->query.qname, namebuf, 5821 1.9 christos sizeof(namebuf)); 5822 1.3 christos dns_rdatatype_format(qctx->qtype, typebuf, sizeof(typebuf)); 5823 1.9 christos dns_rdataclass_format(qctx->client->message->rdclass, classbuf, 5824 1.9 christos sizeof(classbuf)); 5825 1.1 christos ns_client_log(qctx->client, DNS_LOGCATEGORY_SECURITY, 5826 1.1 christos NS_LOGMODULE_QUERY, ISC_LOG_ERROR, 5827 1.9 christos "check-names failure %s/%s/%s", namebuf, typebuf, 5828 1.9 christos classbuf); 5829 1.1 christos QUERY_ERROR(qctx, DNS_R_REFUSED); 5830 1.23 christos return ns_query_done(qctx); 5831 1.1 christos } 5832 1.1 christos 5833 1.1 christos /* 5834 1.1 christos * Setup for root key sentinel processing. 5835 1.1 christos */ 5836 1.3 christos if (qctx->view->root_key_sentinel && 5837 1.1 christos qctx->client->query.restarts == 0 && 5838 1.1 christos (qctx->qtype == dns_rdatatype_a || 5839 1.1 christos qctx->qtype == dns_rdatatype_aaaa) && 5840 1.1 christos (qctx->client->message->flags & DNS_MESSAGEFLAG_CD) == 0) 5841 1.1 christos { 5842 1.9 christos root_key_sentinel_detect(qctx); 5843 1.1 christos } 5844 1.1 christos 5845 1.1 christos /* 5846 1.23 christos * First we must find the right database. Reset the options but preserve 5847 1.23 christos * the 'nolog' flag. 5848 1.1 christos */ 5849 1.23 christos qctx->options = (dns_getdb_options_t){ .nolog = qctx->options.nolog }; 5850 1.1 christos if (dns_rdatatype_atparent(qctx->qtype) && 5851 1.1 christos !dns_name_equal(qctx->client->query.qname, dns_rootname)) 5852 1.1 christos { 5853 1.1 christos /* 5854 1.1 christos * If authoritative data for this QTYPE is supposed to live in 5855 1.1 christos * the parent zone, do not look for an exact match for QNAME, 5856 1.1 christos * but rather for its containing zone (unless the QNAME is 5857 1.1 christos * root). 5858 1.1 christos */ 5859 1.23 christos qctx->options.noexact = true; 5860 1.1 christos } 5861 1.1 christos 5862 1.1 christos result = query_getdb(qctx->client, qctx->client->query.qname, 5863 1.9 christos qctx->qtype, qctx->options, &qctx->zone, &qctx->db, 5864 1.9 christos &qctx->version, &qctx->is_zone); 5865 1.20 christos if ((result != ISC_R_SUCCESS || !qctx->is_zone) && 5866 1.20 christos qctx->qtype == dns_rdatatype_ds && !RECURSIONOK(qctx->client) && 5867 1.23 christos qctx->options.noexact) 5868 1.1 christos { 5869 1.1 christos /* 5870 1.1 christos * This is a non-recursive QTYPE=DS query with QNAME whose 5871 1.1 christos * parent we are not authoritative for. Check whether we are 5872 1.1 christos * authoritative for QNAME, because if so, we need to send a 5873 1.1 christos * "no data" response as required by RFC 4035, section 3.1.4.1. 5874 1.1 christos */ 5875 1.1 christos dns_db_t *tdb = NULL; 5876 1.1 christos dns_zone_t *tzone = NULL; 5877 1.1 christos dns_dbversion_t *tversion = NULL; 5878 1.1 christos isc_result_t tresult; 5879 1.1 christos 5880 1.23 christos dns_getdb_options_t options = { .partial = true }; 5881 1.9 christos tresult = query_getzonedb( 5882 1.9 christos qctx->client, qctx->client->query.qname, qctx->qtype, 5883 1.23 christos options, &tzone, &tdb, &tversion); 5884 1.1 christos if (tresult == ISC_R_SUCCESS) { 5885 1.1 christos /* 5886 1.1 christos * We are authoritative for QNAME. Attach the relevant 5887 1.1 christos * zone to query context, set result to ISC_R_SUCCESS. 5888 1.1 christos */ 5889 1.23 christos qctx->options.noexact = false; 5890 1.3 christos ns_client_putrdataset(qctx->client, &qctx->rdataset); 5891 1.1 christos if (qctx->db != NULL) { 5892 1.1 christos dns_db_detach(&qctx->db); 5893 1.1 christos } 5894 1.1 christos if (qctx->zone != NULL) { 5895 1.1 christos dns_zone_detach(&qctx->zone); 5896 1.1 christos } 5897 1.1 christos qctx->version = NULL; 5898 1.1 christos RESTORE(qctx->version, tversion); 5899 1.1 christos RESTORE(qctx->db, tdb); 5900 1.1 christos RESTORE(qctx->zone, tzone); 5901 1.3 christos qctx->is_zone = true; 5902 1.1 christos result = ISC_R_SUCCESS; 5903 1.1 christos } else { 5904 1.1 christos /* 5905 1.1 christos * We are not authoritative for QNAME. Clean up and 5906 1.1 christos * leave result as it was. 5907 1.1 christos */ 5908 1.1 christos if (tdb != NULL) { 5909 1.1 christos dns_db_detach(&tdb); 5910 1.1 christos } 5911 1.1 christos if (tzone != NULL) { 5912 1.1 christos dns_zone_detach(&tzone); 5913 1.1 christos } 5914 1.1 christos } 5915 1.1 christos } 5916 1.1 christos /* 5917 1.1 christos * If we did not find a database from which we can answer the query, 5918 1.1 christos * respond with either REFUSED or SERVFAIL, depending on what the 5919 1.1 christos * result of query_getdb() was. 5920 1.1 christos */ 5921 1.1 christos if (result != ISC_R_SUCCESS) { 5922 1.1 christos if (result == DNS_R_REFUSED) { 5923 1.1 christos if (WANTRECURSION(qctx->client)) { 5924 1.24 christos dns_ede_add(&qctx->client->edectx, 5925 1.24 christos DNS_EDE_NOTAUTH, 5926 1.24 christos "recursion disabled"); 5927 1.1 christos inc_stats(qctx->client, 5928 1.1 christos ns_statscounter_recurserej); 5929 1.1 christos } else { 5930 1.1 christos inc_stats(qctx->client, 5931 1.1 christos ns_statscounter_authrej); 5932 1.1 christos } 5933 1.1 christos if (!PARTIALANSWER(qctx->client)) { 5934 1.1 christos QUERY_ERROR(qctx, DNS_R_REFUSED); 5935 1.1 christos } 5936 1.1 christos } else { 5937 1.9 christos CCTRACE(ISC_LOG_ERROR, "ns__query_start: query_getdb " 5938 1.9 christos "failed"); 5939 1.3 christos QUERY_ERROR(qctx, result); 5940 1.1 christos } 5941 1.23 christos return ns_query_done(qctx); 5942 1.1 christos } 5943 1.1 christos 5944 1.1 christos /* 5945 1.1 christos * We found a database from which we can answer the query. Update 5946 1.1 christos * relevant query context flags if the answer is to be prepared using 5947 1.1 christos * authoritative data. 5948 1.1 christos */ 5949 1.3 christos qctx->is_staticstub_zone = false; 5950 1.1 christos if (qctx->is_zone) { 5951 1.3 christos qctx->authoritative = true; 5952 1.3 christos if (qctx->zone != NULL) { 5953 1.3 christos if (dns_zone_gettype(qctx->zone) == dns_zone_mirror) { 5954 1.3 christos qctx->authoritative = false; 5955 1.3 christos } 5956 1.9 christos if (dns_zone_gettype(qctx->zone) == dns_zone_staticstub) 5957 1.3 christos { 5958 1.3 christos qctx->is_staticstub_zone = true; 5959 1.3 christos } 5960 1.1 christos } 5961 1.1 christos } 5962 1.1 christos 5963 1.1 christos /* 5964 1.1 christos * Attach to the database which will be used to prepare the answer. 5965 1.1 christos * Update query statistics. 5966 1.1 christos */ 5967 1.23 christos if (qctx->fresp == NULL && qctx->client->query.restarts == 0) { 5968 1.1 christos if (qctx->is_zone) { 5969 1.1 christos if (qctx->zone != NULL) { 5970 1.1 christos /* 5971 1.1 christos * if is_zone = true, zone = NULL then this is 5972 1.1 christos * a DLZ zone. Don't attempt to attach zone. 5973 1.1 christos */ 5974 1.1 christos dns_zone_attach(qctx->zone, 5975 1.1 christos &qctx->client->query.authzone); 5976 1.1 christos } 5977 1.1 christos dns_db_attach(qctx->db, &qctx->client->query.authdb); 5978 1.1 christos } 5979 1.3 christos qctx->client->query.authdbset = true; 5980 1.1 christos 5981 1.1 christos /* Track TCP vs UDP stats per zone */ 5982 1.1 christos if (TCP(qctx->client)) { 5983 1.1 christos inc_stats(qctx->client, ns_statscounter_tcp); 5984 1.1 christos } else { 5985 1.1 christos inc_stats(qctx->client, ns_statscounter_udp); 5986 1.1 christos } 5987 1.1 christos } 5988 1.1 christos 5989 1.25 christos /* 5990 1.25 christos * If stale answers are enabled and stale-answer-client-timeout is zero, 5991 1.25 christos * then we can promptly answer with a stale RRset if one is available in 5992 1.25 christos * cache. 5993 1.25 christos */ 5994 1.25 christos qctx->options.stalefirst = (!qctx->is_zone && 5995 1.25 christos qctx->view->staleanswerclienttimeout == 0 && 5996 1.25 christos dns_view_staleanswerenabled(qctx->view)); 5997 1.11 christos 5998 1.11 christos result = query_lookup(qctx); 5999 1.11 christos 6000 1.11 christos /* 6001 1.11 christos * Clear "look-also-for-stale-data" flag. 6002 1.11 christos * If a fetch is created to resolve this query, then, 6003 1.11 christos * when it completes, this option is not expected to be set. 6004 1.11 christos */ 6005 1.23 christos qctx->options.stalefirst = false; 6006 1.3 christos 6007 1.9 christos cleanup: 6008 1.23 christos return result; 6009 1.23 christos } 6010 1.23 christos 6011 1.23 christos static void 6012 1.23 christos async_restart(void *arg) { 6013 1.23 christos query_ctx_t *qctx = arg; 6014 1.23 christos ns_client_t *client = qctx->client; 6015 1.23 christos isc_nmhandle_t *handle = client->restarthandle; 6016 1.23 christos 6017 1.23 christos client->restarthandle = NULL; 6018 1.23 christos 6019 1.23 christos ns__query_start(qctx); 6020 1.23 christos 6021 1.23 christos qctx_clean(qctx); 6022 1.23 christos qctx_freedata(qctx); 6023 1.23 christos qctx_destroy(qctx); 6024 1.23 christos isc_mem_put(client->manager->mctx, qctx, sizeof(*qctx)); 6025 1.23 christos isc_nmhandle_detach(&handle); 6026 1.1 christos } 6027 1.1 christos 6028 1.11 christos /* 6029 1.11 christos * Allocate buffers in 'qctx' used to store query results. 6030 1.11 christos * 6031 1.11 christos * 'buffer' must be a pointer to an object whose lifetime 6032 1.11 christos * doesn't expire while 'qctx' is in use. 6033 1.11 christos */ 6034 1.11 christos static isc_result_t 6035 1.11 christos qctx_prepare_buffers(query_ctx_t *qctx, isc_buffer_t *buffer) { 6036 1.11 christos REQUIRE(qctx != NULL); 6037 1.11 christos REQUIRE(qctx->client != NULL); 6038 1.11 christos REQUIRE(buffer != NULL); 6039 1.11 christos 6040 1.11 christos qctx->dbuf = ns_client_getnamebuf(qctx->client); 6041 1.11 christos qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, buffer); 6042 1.11 christos qctx->rdataset = ns_client_newrdataset(qctx->client); 6043 1.11 christos 6044 1.11 christos if ((WANTDNSSEC(qctx->client) || qctx->findcoveringnsec) && 6045 1.11 christos (!qctx->is_zone || dns_db_issecure(qctx->db))) 6046 1.11 christos { 6047 1.11 christos qctx->sigrdataset = ns_client_newrdataset(qctx->client); 6048 1.11 christos } 6049 1.11 christos 6050 1.23 christos return ISC_R_SUCCESS; 6051 1.11 christos } 6052 1.11 christos 6053 1.1 christos /*% 6054 1.17 christos * Depending on the db lookup result, we can respond to the 6055 1.17 christos * client this stale answer. 6056 1.17 christos */ 6057 1.17 christos static bool 6058 1.17 christos stale_client_answer(isc_result_t result) { 6059 1.17 christos switch (result) { 6060 1.17 christos case ISC_R_SUCCESS: 6061 1.17 christos case DNS_R_EMPTYNAME: 6062 1.17 christos case DNS_R_NXRRSET: 6063 1.17 christos case DNS_R_NCACHENXRRSET: 6064 1.17 christos case DNS_R_CNAME: 6065 1.17 christos case DNS_R_DNAME: 6066 1.23 christos return true; 6067 1.17 christos default: 6068 1.23 christos return false; 6069 1.17 christos } 6070 1.17 christos 6071 1.17 christos UNREACHABLE(); 6072 1.17 christos } 6073 1.17 christos 6074 1.17 christos /*% 6075 1.1 christos * Perform a local database lookup, in either an authoritative or 6076 1.3 christos * cache database. If unable to answer, call ns_query_done(); otherwise 6077 1.1 christos * hand off processing to query_gotanswer(). 6078 1.1 christos */ 6079 1.1 christos static isc_result_t 6080 1.1 christos query_lookup(query_ctx_t *qctx) { 6081 1.11 christos isc_buffer_t buffer; 6082 1.11 christos isc_result_t result = ISC_R_UNSET; 6083 1.1 christos dns_clientinfomethods_t cm; 6084 1.1 christos dns_clientinfo_t ci; 6085 1.1 christos dns_name_t *rpzqname = NULL; 6086 1.13 christos char namebuf[DNS_NAME_FORMATSIZE]; 6087 1.23 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 6088 1.1 christos unsigned int dboptions; 6089 1.11 christos dns_ttl_t stale_refresh = 0; 6090 1.11 christos bool dbfind_stale = false; 6091 1.13 christos bool stale_timeout = false; 6092 1.16 christos bool answer_found = false; 6093 1.11 christos bool stale_found = false; 6094 1.11 christos bool stale_refresh_window = false; 6095 1.20 christos uint16_t ede = 0; 6096 1.1 christos 6097 1.1 christos CCTRACE(ISC_LOG_DEBUG(3), "query_lookup"); 6098 1.1 christos 6099 1.3 christos CALL_HOOK(NS_QUERY_LOOKUP_BEGIN, qctx); 6100 1.1 christos 6101 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 6102 1.20 christos dns_clientinfo_init(&ci, qctx->client, NULL); 6103 1.20 christos if (HAVEECS(qctx->client)) { 6104 1.20 christos dns_clientinfo_setecs(&ci, &qctx->client->ecs); 6105 1.20 christos } 6106 1.1 christos 6107 1.1 christos /* 6108 1.1 christos * We'll need some resources... 6109 1.1 christos */ 6110 1.11 christos result = qctx_prepare_buffers(qctx, &buffer); 6111 1.11 christos if (result != ISC_R_SUCCESS) { 6112 1.11 christos QUERY_ERROR(qctx, result); 6113 1.23 christos return ns_query_done(qctx); 6114 1.1 christos } 6115 1.1 christos 6116 1.1 christos /* 6117 1.1 christos * Now look for an answer in the database. 6118 1.1 christos */ 6119 1.1 christos if (qctx->dns64 && qctx->rpz) { 6120 1.1 christos rpzqname = qctx->client->query.rpz_st->p_name; 6121 1.1 christos } else { 6122 1.1 christos rpzqname = qctx->client->query.qname; 6123 1.1 christos } 6124 1.1 christos 6125 1.25 christos qctx->client->query.dboptions &= ~DNS_DBFIND_STALETIMEOUT; 6126 1.25 christos 6127 1.25 christos if (qctx->options.stalefirst && !qctx->is_zone) { 6128 1.11 christos /* 6129 1.23 christos * If the 'stalefirst' flag is set, it means that a stale 6130 1.11 christos * RRset may be returned as part of this lookup. An attempt 6131 1.11 christos * to refresh the RRset will still take place if an 6132 1.11 christos * active RRset is not available. 6133 1.11 christos */ 6134 1.13 christos qctx->client->query.dboptions |= DNS_DBFIND_STALETIMEOUT; 6135 1.11 christos } 6136 1.11 christos 6137 1.26 christos (void)dns_db_getservestalerefresh(qctx->client->view->cachedb, 6138 1.26 christos &stale_refresh); 6139 1.26 christos if (stale_refresh > 0 && 6140 1.26 christos dns_view_staleanswerenabled(qctx->client->view)) 6141 1.26 christos { 6142 1.26 christos qctx->client->query.dboptions |= DNS_DBFIND_STALEENABLED; 6143 1.26 christos } 6144 1.26 christos 6145 1.1 christos dboptions = qctx->client->query.dboptions; 6146 1.1 christos if (!qctx->is_zone && qctx->findcoveringnsec && 6147 1.1 christos (qctx->type != dns_rdatatype_null || !dns_name_istat(rpzqname))) 6148 1.9 christos { 6149 1.1 christos dboptions |= DNS_DBFIND_COVERINGNSEC; 6150 1.9 christos } 6151 1.1 christos 6152 1.1 christos result = dns_db_findext(qctx->db, rpzqname, qctx->version, qctx->type, 6153 1.1 christos dboptions, qctx->client->now, &qctx->node, 6154 1.9 christos qctx->fname, &cm, &ci, qctx->rdataset, 6155 1.9 christos qctx->sigrdataset); 6156 1.1 christos 6157 1.1 christos /* 6158 1.1 christos * Fixup fname and sigrdataset. 6159 1.1 christos */ 6160 1.1 christos if (qctx->dns64 && qctx->rpz) { 6161 1.20 christos dns_name_copy(qctx->client->query.qname, qctx->fname); 6162 1.1 christos if (qctx->sigrdataset != NULL && 6163 1.16 christos dns_rdataset_isassociated(qctx->sigrdataset)) 6164 1.16 christos { 6165 1.1 christos dns_rdataset_disassociate(qctx->sigrdataset); 6166 1.1 christos } 6167 1.1 christos } 6168 1.1 christos 6169 1.1 christos if (!qctx->is_zone) { 6170 1.3 christos dns_cache_updatestats(qctx->view->cache, result); 6171 1.1 christos } 6172 1.1 christos 6173 1.11 christos /* 6174 1.11 christos * If DNS_DBFIND_STALEOK is set this means we are dealing with a 6175 1.11 christos * lookup following a failed lookup and it is okay to serve a stale 6176 1.11 christos * answer. This will (re)start the 'stale-refresh-time' window in 6177 1.11 christos * rbtdb, tracking the last time the RRset lookup failed. 6178 1.11 christos */ 6179 1.11 christos dbfind_stale = ((dboptions & DNS_DBFIND_STALEOK) != 0); 6180 1.11 christos 6181 1.11 christos /* 6182 1.11 christos * If DNS_DBFIND_STALEENABLED is set, this may be a normal lookup, but 6183 1.11 christos * we are allowed to immediately respond with a stale answer if the 6184 1.11 christos * request is within the 'stale-refresh-time' window. 6185 1.11 christos */ 6186 1.11 christos stale_refresh_window = (STALE_WINDOW(qctx->rdataset) && 6187 1.11 christos (dboptions & DNS_DBFIND_STALEENABLED) != 0); 6188 1.11 christos 6189 1.11 christos /* 6190 1.13 christos * If DNS_DBFIND_STALETIMEOUT is set, a stale answer is requested. 6191 1.11 christos * This can happen if 'stale-answer-client-timeout' is enabled. 6192 1.11 christos * 6193 1.23 christos * If a stale answer is found, send it to the client, and try to refresh 6194 1.23 christos * the RRset. 6195 1.11 christos */ 6196 1.13 christos stale_timeout = ((dboptions & DNS_DBFIND_STALETIMEOUT) != 0); 6197 1.11 christos 6198 1.16 christos if (dns_rdataset_isassociated(qctx->rdataset) && 6199 1.16 christos dns_rdataset_count(qctx->rdataset) > 0 && !STALE(qctx->rdataset)) 6200 1.16 christos { 6201 1.16 christos /* Found non-stale usable rdataset. */ 6202 1.16 christos answer_found = true; 6203 1.16 christos } 6204 1.16 christos 6205 1.13 christos if (dbfind_stale || stale_refresh_window || stale_timeout) { 6206 1.13 christos dns_name_format(qctx->client->query.qname, namebuf, 6207 1.13 christos sizeof(namebuf)); 6208 1.23 christos dns_rdatatype_format(qctx->qtype, typebuf, sizeof(typebuf)); 6209 1.1 christos 6210 1.11 christos inc_stats(qctx->client, ns_statscounter_trystale); 6211 1.11 christos 6212 1.1 christos if (dns_rdataset_isassociated(qctx->rdataset) && 6213 1.1 christos dns_rdataset_count(qctx->rdataset) > 0 && 6214 1.9 christos STALE(qctx->rdataset)) 6215 1.9 christos { 6216 1.20 christos stale_found = true; 6217 1.20 christos if (result == DNS_R_NCACHENXDOMAIN || 6218 1.20 christos result == DNS_R_NXDOMAIN) 6219 1.20 christos { 6220 1.20 christos ede = DNS_EDE_STALENXANSWER; 6221 1.20 christos } else { 6222 1.20 christos ede = DNS_EDE_STALEANSWER; 6223 1.20 christos } 6224 1.3 christos qctx->rdataset->ttl = qctx->view->staleanswerttl; 6225 1.14 christos inc_stats(qctx->client, ns_statscounter_usedstale); 6226 1.1 christos } else { 6227 1.11 christos stale_found = false; 6228 1.1 christos } 6229 1.13 christos } 6230 1.1 christos 6231 1.13 christos if (dbfind_stale) { 6232 1.13 christos isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE, 6233 1.13 christos NS_LOGMODULE_QUERY, ISC_LOG_INFO, 6234 1.23 christos "%s %s resolver failure, stale answer %s (%s)", 6235 1.23 christos namebuf, typebuf, 6236 1.23 christos stale_found ? "used" : "unavailable", 6237 1.23 christos isc_result_totext(result)); 6238 1.20 christos if (stale_found) { 6239 1.24 christos dns_ede_add(&qctx->client->edectx, ede, 6240 1.24 christos "resolver failure"); 6241 1.20 christos } else if (!answer_found) { 6242 1.13 christos /* 6243 1.13 christos * Resolver failure, no stale data, nothing more we 6244 1.13 christos * can do, return SERVFAIL. 6245 1.13 christos */ 6246 1.13 christos QUERY_ERROR(qctx, DNS_R_SERVFAIL); 6247 1.23 christos return ns_query_done(qctx); 6248 1.13 christos } 6249 1.13 christos } else if (stale_refresh_window) { 6250 1.13 christos /* 6251 1.13 christos * A recent lookup failed, so during this time window we are 6252 1.13 christos * allowed to return stale data immediately. 6253 1.13 christos */ 6254 1.13 christos isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE, 6255 1.13 christos NS_LOGMODULE_QUERY, ISC_LOG_INFO, 6256 1.23 christos "%s %s query within stale refresh time, stale " 6257 1.23 christos "answer %s (%s)", 6258 1.23 christos namebuf, typebuf, 6259 1.23 christos stale_found ? "used" : "unavailable", 6260 1.23 christos isc_result_totext(result)); 6261 1.11 christos 6262 1.20 christos if (stale_found) { 6263 1.24 christos dns_ede_add(&qctx->client->edectx, ede, 6264 1.24 christos "query within stale refresh time window"); 6265 1.20 christos } else if (!answer_found) { 6266 1.11 christos /* 6267 1.13 christos * During the stale refresh window explicitly do not try 6268 1.13 christos * to refresh the data, because a recent lookup failed. 6269 1.11 christos */ 6270 1.13 christos QUERY_ERROR(qctx, DNS_R_SERVFAIL); 6271 1.23 christos return ns_query_done(qctx); 6272 1.13 christos } 6273 1.13 christos } else if (stale_timeout) { 6274 1.23 christos if (qctx->options.stalefirst) { 6275 1.24 christos /* 6276 1.24 christos * If 'qctx->zdb' is set, this was a cache lookup after 6277 1.24 christos * an authoritative lookup returned a delegation (in 6278 1.24 christos * order to find a better answer). But we still can 6279 1.24 christos * return without getting any usable answer here, as 6280 1.24 christos * query_notfound() should handle it from here. 6281 1.24 christos * Otherwise, if nothing useful was found in cache then 6282 1.24 christos * recursively call query_lookup() again without the 6283 1.24 christos * 'stalefirst' option set. 6284 1.24 christos */ 6285 1.24 christos if (!stale_found && !answer_found && qctx->zdb == NULL) 6286 1.24 christos { 6287 1.13 christos qctx_clean(qctx); 6288 1.13 christos qctx_freedata(qctx); 6289 1.13 christos dns_db_attach(qctx->client->view->cachedb, 6290 1.13 christos &qctx->db); 6291 1.23 christos qctx->options.stalefirst = false; 6292 1.23 christos if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL) 6293 1.23 christos { 6294 1.13 christos dns_resolver_destroyfetch( 6295 1.23 christos &FETCH_RECTYPE_NORMAL( 6296 1.23 christos qctx->client)); 6297 1.11 christos } 6298 1.23 christos return query_lookup(qctx); 6299 1.17 christos } else if (stale_client_answer(result)) { 6300 1.11 christos /* 6301 1.13 christos * Immediately return the stale answer, start a 6302 1.13 christos * resolver fetch to refresh the data in cache. 6303 1.11 christos */ 6304 1.20 christos if (stale_found) { 6305 1.24 christos dns_ede_add( 6306 1.24 christos &qctx->client->edectx, ede, 6307 1.20 christos "stale data prioritized over " 6308 1.20 christos "lookup"); 6309 1.20 christos } 6310 1.13 christos } 6311 1.13 christos } else { 6312 1.23 christos UNREACHABLE(); 6313 1.1 christos } 6314 1.11 christos } 6315 1.11 christos 6316 1.11 christos result = query_gotanswer(qctx, result); 6317 1.11 christos 6318 1.9 christos cleanup: 6319 1.23 christos return result; 6320 1.1 christos } 6321 1.1 christos 6322 1.1 christos /* 6323 1.11 christos * Event handler to resume processing a query after recursion, or when a 6324 1.11 christos * client timeout is triggered. If the query has timed out or been cancelled 6325 1.11 christos * or the system is shutting down, clean up and exit. If a client timeout is 6326 1.11 christos * triggered, see if we can respond with a stale answer from cache. Otherwise, 6327 1.11 christos * call query_resume() to continue the ongoing work. 6328 1.1 christos */ 6329 1.1 christos static void 6330 1.23 christos fetch_callback(void *arg) { 6331 1.23 christos dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg; 6332 1.23 christos ns_client_t *client = resp->arg; 6333 1.1 christos dns_fetch_t *fetch = NULL; 6334 1.14 christos bool fetch_canceled = false; 6335 1.14 christos isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_ERRORS; 6336 1.1 christos isc_result_t result; 6337 1.1 christos int errorloglevel; 6338 1.11 christos query_ctx_t qctx; 6339 1.1 christos 6340 1.1 christos REQUIRE(NS_CLIENT_VALID(client)); 6341 1.1 christos REQUIRE(RECURSING(client)); 6342 1.1 christos 6343 1.9 christos CTRACE(ISC_LOG_DEBUG(3), "fetch_callback"); 6344 1.9 christos 6345 1.13 christos /* 6346 1.13 christos * We are resuming from recursion. Reset any attributes, options 6347 1.13 christos * that a lookup due to stale-answer-client-timeout may have set. 6348 1.13 christos */ 6349 1.13 christos if (client->view->cachedb != NULL && client->view->recursion) { 6350 1.13 christos client->query.attributes |= NS_QUERYATTR_RECURSIONOK; 6351 1.13 christos } 6352 1.13 christos client->query.dboptions &= ~DNS_DBFIND_STALETIMEOUT; 6353 1.26 christos client->query.dboptions &= ~DNS_DBFIND_STALEENABLED; 6354 1.13 christos 6355 1.1 christos LOCK(&client->query.fetchlock); 6356 1.23 christos INSIST(FETCH_RECTYPE_NORMAL(client) == resp->fetch || 6357 1.23 christos FETCH_RECTYPE_NORMAL(client) == NULL); 6358 1.23 christos if (FETCH_RECTYPE_NORMAL(client) != NULL) { 6359 1.1 christos /* 6360 1.1 christos * This is the fetch we've been waiting for. 6361 1.1 christos */ 6362 1.23 christos INSIST(FETCH_RECTYPE_NORMAL(client) == resp->fetch); 6363 1.23 christos FETCH_RECTYPE_NORMAL(client) = NULL; 6364 1.14 christos 6365 1.1 christos /* 6366 1.1 christos * Update client->now. 6367 1.1 christos */ 6368 1.23 christos client->now = isc_stdtime_now(); 6369 1.1 christos } else { 6370 1.1 christos /* 6371 1.1 christos * This is a fetch completion event for a canceled fetch. 6372 1.1 christos * Clean up and don't resume the find. 6373 1.1 christos */ 6374 1.3 christos fetch_canceled = true; 6375 1.1 christos } 6376 1.1 christos UNLOCK(&client->query.fetchlock); 6377 1.1 christos 6378 1.23 christos SAVE(fetch, resp->fetch); 6379 1.9 christos 6380 1.9 christos /* 6381 1.9 christos * We're done recursing, detach from quota and unlink from 6382 1.9 christos * the manager's recursing-clients list. 6383 1.9 christos */ 6384 1.23 christos release_recursionquota(client); 6385 1.9 christos 6386 1.23 christos isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client)); 6387 1.11 christos 6388 1.1 christos client->query.attributes &= ~NS_QUERYATTR_RECURSING; 6389 1.9 christos client->state = NS_CLIENTSTATE_WORKING; 6390 1.1 christos 6391 1.1 christos /* 6392 1.11 christos * Initialize a new qctx and use it to either resume from 6393 1.11 christos * recursion or clean up after cancelation. Transfer 6394 1.23 christos * ownership of resp to the new qctx in the process. 6395 1.1 christos */ 6396 1.23 christos qctx_init(client, &resp, 0, &qctx); 6397 1.11 christos 6398 1.23 christos if (fetch_canceled) { 6399 1.11 christos /* 6400 1.11 christos * We've timed out or are shutting down. We can now 6401 1.11 christos * free the event and other resources held by qctx, but 6402 1.11 christos * don't call qctx_destroy() yet: it might destroy the 6403 1.11 christos * client, which we still need for a moment. 6404 1.11 christos */ 6405 1.11 christos qctx_freedata(&qctx); 6406 1.11 christos 6407 1.11 christos /* 6408 1.23 christos * Return an error to the client. 6409 1.11 christos */ 6410 1.23 christos CTRACE(ISC_LOG_ERROR, "fetch cancelled"); 6411 1.23 christos query_error(client, DNS_R_SERVFAIL, __LINE__); 6412 1.11 christos 6413 1.11 christos /* 6414 1.11 christos * Free any persistent plugin data that was allocated to 6415 1.11 christos * service the client, then detach the client object. 6416 1.11 christos */ 6417 1.11 christos qctx.detach_client = true; 6418 1.11 christos qctx_destroy(&qctx); 6419 1.1 christos } else { 6420 1.3 christos /* 6421 1.11 christos * Resume the find process. 6422 1.3 christos */ 6423 1.1 christos query_trace(&qctx); 6424 1.1 christos 6425 1.1 christos result = query_resume(&qctx); 6426 1.1 christos if (result != ISC_R_SUCCESS) { 6427 1.1 christos if (result == DNS_R_SERVFAIL) { 6428 1.1 christos errorloglevel = ISC_LOG_DEBUG(2); 6429 1.1 christos } else { 6430 1.1 christos errorloglevel = ISC_LOG_DEBUG(4); 6431 1.1 christos } 6432 1.1 christos if (isc_log_wouldlog(ns_lctx, errorloglevel)) { 6433 1.1 christos dns_resolver_logfetch(fetch, ns_lctx, 6434 1.1 christos logcategory, 6435 1.1 christos NS_LOGMODULE_QUERY, 6436 1.3 christos errorloglevel, false); 6437 1.1 christos } 6438 1.1 christos } 6439 1.3 christos 6440 1.3 christos qctx_destroy(&qctx); 6441 1.1 christos } 6442 1.1 christos 6443 1.1 christos dns_resolver_destroyfetch(&fetch); 6444 1.1 christos } 6445 1.1 christos 6446 1.1 christos /*% 6447 1.1 christos * Check whether the recursion parameters in 'param' match the current query's 6448 1.1 christos * recursion parameters provided in 'qtype', 'qname', and 'qdomain'. 6449 1.1 christos */ 6450 1.3 christos static bool 6451 1.1 christos recparam_match(const ns_query_recparam_t *param, dns_rdatatype_t qtype, 6452 1.9 christos const dns_name_t *qname, const dns_name_t *qdomain) { 6453 1.1 christos REQUIRE(param != NULL); 6454 1.1 christos 6455 1.23 christos return param->qtype == qtype && param->qname != NULL && qname != NULL && 6456 1.23 christos param->qdomain != NULL && qdomain != NULL && 6457 1.23 christos dns_name_equal(param->qname, qname) && 6458 1.23 christos dns_name_equal(param->qdomain, qdomain); 6459 1.1 christos } 6460 1.1 christos 6461 1.1 christos /*% 6462 1.1 christos * Update 'param' with current query's recursion parameters provided in 6463 1.1 christos * 'qtype', 'qname', and 'qdomain'. 6464 1.1 christos */ 6465 1.1 christos static void 6466 1.1 christos recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype, 6467 1.9 christos const dns_name_t *qname, const dns_name_t *qdomain) { 6468 1.1 christos REQUIRE(param != NULL); 6469 1.1 christos 6470 1.1 christos param->qtype = qtype; 6471 1.1 christos 6472 1.1 christos if (qname == NULL) { 6473 1.1 christos param->qname = NULL; 6474 1.1 christos } else { 6475 1.3 christos param->qname = dns_fixedname_initname(¶m->fqname); 6476 1.20 christos dns_name_copy(qname, param->qname); 6477 1.1 christos } 6478 1.1 christos 6479 1.1 christos if (qdomain == NULL) { 6480 1.1 christos param->qdomain = NULL; 6481 1.1 christos } else { 6482 1.3 christos param->qdomain = dns_fixedname_initname(¶m->fqdomain); 6483 1.20 christos dns_name_copy(qdomain, param->qdomain); 6484 1.1 christos } 6485 1.1 christos } 6486 1.23 christos 6487 1.23 christos static void 6488 1.23 christos recursionquota_log(ns_client_t *client, atomic_uint_fast32_t *last_log_time, 6489 1.23 christos const char *format, isc_quota_t *quota) { 6490 1.23 christos isc_stdtime_t now = isc_stdtime_now(); 6491 1.23 christos if (now == atomic_load_relaxed(last_log_time)) { 6492 1.23 christos return; 6493 1.23 christos } 6494 1.23 christos 6495 1.23 christos atomic_store_relaxed(last_log_time, now); 6496 1.23 christos ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, 6497 1.23 christos ISC_LOG_WARNING, format, isc_quota_getused(quota), 6498 1.23 christos isc_quota_getsoft(quota), isc_quota_getmax(quota)); 6499 1.23 christos } 6500 1.23 christos 6501 1.9 christos static atomic_uint_fast32_t last_soft, last_hard; 6502 1.1 christos 6503 1.20 christos /*% 6504 1.23 christos * Acquire recursion quota before making the current client "recursing". 6505 1.20 christos */ 6506 1.20 christos static isc_result_t 6507 1.23 christos acquire_recursionquota(ns_client_t *client) { 6508 1.23 christos isc_result_t result; 6509 1.23 christos 6510 1.23 christos result = recursionquotatype_attach_soft(client); 6511 1.23 christos switch (result) { 6512 1.23 christos case ISC_R_SOFTQUOTA: 6513 1.23 christos recursionquota_log(client, &last_soft, 6514 1.23 christos "recursive-clients soft limit exceeded " 6515 1.23 christos "(%u/%u/%u), aborting oldest query", 6516 1.23 christos &client->manager->sctx->recursionquota); 6517 1.23 christos ns_client_killoldestquery(client); 6518 1.23 christos FALLTHROUGH; 6519 1.23 christos case ISC_R_SUCCESS: 6520 1.23 christos break; 6521 1.23 christos case ISC_R_QUOTA: 6522 1.23 christos recursionquota_log(client, &last_hard, 6523 1.23 christos "no more recursive clients (%u/%u/%u)", 6524 1.23 christos &client->manager->sctx->recursionquota); 6525 1.23 christos ns_client_killoldestquery(client); 6526 1.23 christos return result; 6527 1.23 christos default: 6528 1.23 christos UNREACHABLE(); 6529 1.23 christos } 6530 1.23 christos 6531 1.23 christos dns_message_clonebuffer(client->message); 6532 1.23 christos ns_client_recursing(client); 6533 1.23 christos 6534 1.23 christos return ISC_R_SUCCESS; 6535 1.23 christos } 6536 1.1 christos 6537 1.23 christos /*% 6538 1.23 christos * Release recursion quota and remove the client from the "recursing" list. 6539 1.23 christos */ 6540 1.23 christos static void 6541 1.23 christos release_recursionquota(ns_client_t *client) { 6542 1.23 christos recursionquotatype_detach(client); 6543 1.9 christos 6544 1.23 christos LOCK(&client->manager->reclock); 6545 1.23 christos if (ISC_LINK_LINKED(client, rlink)) { 6546 1.23 christos ISC_LIST_UNLINK(client->manager->recursing, client, rlink); 6547 1.1 christos } 6548 1.23 christos UNLOCK(&client->manager->reclock); 6549 1.20 christos } 6550 1.20 christos 6551 1.20 christos isc_result_t 6552 1.20 christos ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, 6553 1.20 christos dns_name_t *qdomain, dns_rdataset_t *nameservers, 6554 1.20 christos bool resuming) { 6555 1.20 christos isc_result_t result; 6556 1.20 christos dns_rdataset_t *rdataset, *sigrdataset; 6557 1.20 christos isc_sockaddr_t *peeraddr = NULL; 6558 1.20 christos 6559 1.20 christos CTRACE(ISC_LOG_DEBUG(3), "ns_query_recurse"); 6560 1.20 christos 6561 1.20 christos /* 6562 1.20 christos * Check recursion parameters from the previous query to see if they 6563 1.20 christos * match. If not, update recursion parameters and proceed. 6564 1.20 christos */ 6565 1.20 christos if (recparam_match(&client->query.recparam, qtype, qname, qdomain)) { 6566 1.20 christos ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, 6567 1.20 christos ISC_LOG_INFO, "recursion loop detected"); 6568 1.23 christos return ISC_R_FAILURE; 6569 1.20 christos } 6570 1.20 christos 6571 1.20 christos recparam_update(&client->query.recparam, qtype, qname, qdomain); 6572 1.20 christos 6573 1.20 christos if (!resuming) { 6574 1.20 christos inc_stats(client, ns_statscounter_recursion); 6575 1.20 christos } 6576 1.20 christos 6577 1.23 christos result = acquire_recursionquota(client); 6578 1.20 christos if (result != ISC_R_SUCCESS) { 6579 1.23 christos return result; 6580 1.20 christos } 6581 1.20 christos 6582 1.1 christos /* 6583 1.1 christos * Invoke the resolver. 6584 1.1 christos */ 6585 1.1 christos REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns); 6586 1.23 christos REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL); 6587 1.1 christos 6588 1.3 christos rdataset = ns_client_newrdataset(client); 6589 1.1 christos 6590 1.1 christos if (WANTDNSSEC(client)) { 6591 1.3 christos sigrdataset = ns_client_newrdataset(client); 6592 1.1 christos } else { 6593 1.1 christos sigrdataset = NULL; 6594 1.1 christos } 6595 1.1 christos 6596 1.10 christos if (!client->query.timerset) { 6597 1.1 christos ns_client_settimeout(client, 60); 6598 1.1 christos } 6599 1.1 christos 6600 1.1 christos if (!TCP(client)) { 6601 1.1 christos peeraddr = &client->peeraddr; 6602 1.1 christos } 6603 1.1 christos 6604 1.23 christos isc_nmhandle_attach(client->handle, &HANDLE_RECTYPE_NORMAL(client)); 6605 1.9 christos result = dns_resolver_createfetch( 6606 1.9 christos client->view->resolver, qname, qtype, qdomain, nameservers, 6607 1.9 christos NULL, peeraddr, client->message->id, client->query.fetchoptions, 6608 1.26 christos 0, NULL, client->query.qc, NULL, client->manager->loop, 6609 1.24 christos fetch_callback, client, &client->edectx, rdataset, sigrdataset, 6610 1.24 christos &FETCH_RECTYPE_NORMAL(client)); 6611 1.1 christos if (result != ISC_R_SUCCESS) { 6612 1.23 christos release_recursionquota(client); 6613 1.23 christos 6614 1.3 christos ns_client_putrdataset(client, &rdataset); 6615 1.1 christos if (sigrdataset != NULL) { 6616 1.3 christos ns_client_putrdataset(client, &sigrdataset); 6617 1.1 christos } 6618 1.23 christos 6619 1.23 christos isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client)); 6620 1.1 christos } 6621 1.1 christos 6622 1.1 christos /* 6623 1.1 christos * We're now waiting for a fetch event. A client which is 6624 1.1 christos * shutting down will not be destroyed until all the events 6625 1.1 christos * have been received. 6626 1.1 christos */ 6627 1.1 christos 6628 1.23 christos return result; 6629 1.1 christos } 6630 1.1 christos 6631 1.1 christos /*% 6632 1.1 christos * Restores the query context after resuming from recursion, and 6633 1.1 christos * continues the query processing if needed. 6634 1.1 christos */ 6635 1.1 christos static isc_result_t 6636 1.1 christos query_resume(query_ctx_t *qctx) { 6637 1.20 christos isc_result_t result = ISC_R_UNSET; 6638 1.1 christos dns_name_t *tname; 6639 1.1 christos isc_buffer_t b; 6640 1.1 christos #ifdef WANT_QUERYTRACE 6641 1.6 christos char mbuf[4 * DNS_NAME_FORMATSIZE]; 6642 1.1 christos char qbuf[DNS_NAME_FORMATSIZE]; 6643 1.1 christos char tbuf[DNS_RDATATYPE_FORMATSIZE]; 6644 1.9 christos #endif /* ifdef WANT_QUERYTRACE */ 6645 1.9 christos 6646 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_resume"); 6647 1.1 christos 6648 1.3 christos CALL_HOOK(NS_QUERY_RESUME_BEGIN, qctx); 6649 1.3 christos 6650 1.3 christos qctx->want_restart = false; 6651 1.1 christos 6652 1.1 christos qctx->rpz_st = qctx->client->query.rpz_st; 6653 1.1 christos if (qctx->rpz_st != NULL && 6654 1.16 christos (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0) 6655 1.16 christos { 6656 1.1 christos CCTRACE(ISC_LOG_DEBUG(3), "resume from RPZ recursion"); 6657 1.1 christos #ifdef WANT_QUERYTRACE 6658 1.1 christos { 6659 1.1 christos char pbuf[DNS_NAME_FORMATSIZE] = "<unset>"; 6660 1.1 christos char fbuf[DNS_NAME_FORMATSIZE] = "<unset>"; 6661 1.9 christos if (qctx->rpz_st->r_name != NULL) { 6662 1.9 christos dns_name_format(qctx->rpz_st->r_name, qbuf, 6663 1.9 christos sizeof(qbuf)); 6664 1.9 christos } else { 6665 1.9 christos snprintf(qbuf, sizeof(qbuf), "<unset>"); 6666 1.9 christos } 6667 1.9 christos if (qctx->rpz_st->p_name != NULL) { 6668 1.9 christos dns_name_format(qctx->rpz_st->p_name, pbuf, 6669 1.9 christos sizeof(pbuf)); 6670 1.9 christos } 6671 1.9 christos if (qctx->rpz_st->fname != NULL) { 6672 1.9 christos dns_name_format(qctx->rpz_st->fname, fbuf, 6673 1.9 christos sizeof(fbuf)); 6674 1.9 christos } 6675 1.1 christos 6676 1.1 christos snprintf(mbuf, sizeof(mbuf) - 1, 6677 1.9 christos "rpz rname:%s, pname:%s, qctx->fname:%s", qbuf, 6678 1.9 christos pbuf, fbuf); 6679 1.1 christos CCTRACE(ISC_LOG_DEBUG(3), mbuf); 6680 1.1 christos } 6681 1.9 christos #endif /* ifdef WANT_QUERYTRACE */ 6682 1.1 christos 6683 1.1 christos qctx->is_zone = qctx->rpz_st->q.is_zone; 6684 1.1 christos qctx->authoritative = qctx->rpz_st->q.authoritative; 6685 1.1 christos RESTORE(qctx->zone, qctx->rpz_st->q.zone); 6686 1.1 christos RESTORE(qctx->node, qctx->rpz_st->q.node); 6687 1.1 christos RESTORE(qctx->db, qctx->rpz_st->q.db); 6688 1.1 christos RESTORE(qctx->rdataset, qctx->rpz_st->q.rdataset); 6689 1.1 christos RESTORE(qctx->sigrdataset, qctx->rpz_st->q.sigrdataset); 6690 1.1 christos qctx->qtype = qctx->rpz_st->q.qtype; 6691 1.1 christos 6692 1.23 christos if (qctx->fresp->node != NULL) { 6693 1.23 christos dns_db_detachnode(qctx->fresp->db, &qctx->fresp->node); 6694 1.9 christos } 6695 1.23 christos SAVE(qctx->rpz_st->r.db, qctx->fresp->db); 6696 1.23 christos qctx->rpz_st->r.r_type = qctx->fresp->qtype; 6697 1.23 christos SAVE(qctx->rpz_st->r.r_rdataset, qctx->fresp->rdataset); 6698 1.23 christos ns_client_putrdataset(qctx->client, &qctx->fresp->sigrdataset); 6699 1.1 christos } else if (REDIRECT(qctx->client)) { 6700 1.1 christos /* 6701 1.1 christos * Restore saved state. 6702 1.1 christos */ 6703 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "resume from redirect recursion"); 6704 1.1 christos #ifdef WANT_QUERYTRACE 6705 1.9 christos dns_name_format(qctx->client->query.redirect.fname, qbuf, 6706 1.9 christos sizeof(qbuf)); 6707 1.9 christos dns_rdatatype_format(qctx->client->query.redirect.qtype, tbuf, 6708 1.9 christos sizeof(tbuf)); 6709 1.1 christos snprintf(mbuf, sizeof(mbuf) - 1, 6710 1.9 christos "redirect qctx->fname:%s, qtype:%s, auth:%d", qbuf, 6711 1.9 christos tbuf, qctx->client->query.redirect.authoritative); 6712 1.1 christos CCTRACE(ISC_LOG_DEBUG(3), mbuf); 6713 1.9 christos #endif /* ifdef WANT_QUERYTRACE */ 6714 1.1 christos qctx->qtype = qctx->client->query.redirect.qtype; 6715 1.1 christos INSIST(qctx->client->query.redirect.rdataset != NULL); 6716 1.1 christos RESTORE(qctx->rdataset, qctx->client->query.redirect.rdataset); 6717 1.1 christos RESTORE(qctx->sigrdataset, 6718 1.1 christos qctx->client->query.redirect.sigrdataset); 6719 1.1 christos RESTORE(qctx->db, qctx->client->query.redirect.db); 6720 1.1 christos RESTORE(qctx->node, qctx->client->query.redirect.node); 6721 1.1 christos RESTORE(qctx->zone, qctx->client->query.redirect.zone); 6722 1.1 christos qctx->authoritative = 6723 1.1 christos qctx->client->query.redirect.authoritative; 6724 1.1 christos 6725 1.1 christos /* 6726 1.1 christos * Free resources used while recursing. 6727 1.1 christos */ 6728 1.23 christos ns_client_putrdataset(qctx->client, &qctx->fresp->rdataset); 6729 1.23 christos ns_client_putrdataset(qctx->client, &qctx->fresp->sigrdataset); 6730 1.23 christos if (qctx->fresp->node != NULL) { 6731 1.23 christos dns_db_detachnode(qctx->fresp->db, &qctx->fresp->node); 6732 1.9 christos } 6733 1.23 christos if (qctx->fresp->db != NULL) { 6734 1.23 christos dns_db_detach(&qctx->fresp->db); 6735 1.9 christos } 6736 1.1 christos } else { 6737 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "resume from normal recursion"); 6738 1.3 christos qctx->authoritative = false; 6739 1.1 christos 6740 1.23 christos qctx->qtype = qctx->fresp->qtype; 6741 1.23 christos SAVE(qctx->db, qctx->fresp->db); 6742 1.23 christos SAVE(qctx->node, qctx->fresp->node); 6743 1.23 christos SAVE(qctx->rdataset, qctx->fresp->rdataset); 6744 1.23 christos SAVE(qctx->sigrdataset, qctx->fresp->sigrdataset); 6745 1.1 christos } 6746 1.1 christos INSIST(qctx->rdataset != NULL); 6747 1.1 christos 6748 1.1 christos if (qctx->qtype == dns_rdatatype_rrsig || 6749 1.16 christos qctx->qtype == dns_rdatatype_sig) 6750 1.16 christos { 6751 1.1 christos qctx->type = dns_rdatatype_any; 6752 1.1 christos } else { 6753 1.1 christos qctx->type = qctx->qtype; 6754 1.1 christos } 6755 1.1 christos 6756 1.3 christos CALL_HOOK(NS_QUERY_RESUME_RESTORED, qctx); 6757 1.3 christos 6758 1.1 christos if (DNS64(qctx->client)) { 6759 1.1 christos qctx->client->query.attributes &= ~NS_QUERYATTR_DNS64; 6760 1.3 christos qctx->dns64 = true; 6761 1.1 christos } 6762 1.1 christos 6763 1.1 christos if (DNS64EXCLUDE(qctx->client)) { 6764 1.1 christos qctx->client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE; 6765 1.3 christos qctx->dns64_exclude = true; 6766 1.1 christos } 6767 1.1 christos 6768 1.1 christos if (qctx->rpz_st != NULL && 6769 1.16 christos (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0) 6770 1.16 christos { 6771 1.1 christos /* 6772 1.1 christos * Has response policy changed out from under us? 6773 1.1 christos */ 6774 1.24 christos if (qctx->view->rpzs == NULL || 6775 1.24 christos qctx->rpz_st->rpz_ver != qctx->view->rpzs->rpz_ver) 6776 1.24 christos { 6777 1.1 christos ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT, 6778 1.9 christos NS_LOGMODULE_QUERY, DNS_RPZ_INFO_LEVEL, 6779 1.24 christos "query_resume: RPZ settings out of date " 6780 1.24 christos "after of a reconfiguration"); 6781 1.1 christos QUERY_ERROR(qctx, DNS_R_SERVFAIL); 6782 1.23 christos return ns_query_done(qctx); 6783 1.1 christos } 6784 1.1 christos } 6785 1.1 christos 6786 1.1 christos /* 6787 1.1 christos * We'll need some resources... 6788 1.1 christos */ 6789 1.3 christos qctx->dbuf = ns_client_getnamebuf(qctx->client); 6790 1.3 christos qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b); 6791 1.1 christos 6792 1.1 christos if (qctx->rpz_st != NULL && 6793 1.16 christos (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0) 6794 1.16 christos { 6795 1.1 christos tname = qctx->rpz_st->fname; 6796 1.1 christos } else if (REDIRECT(qctx->client)) { 6797 1.1 christos tname = qctx->client->query.redirect.fname; 6798 1.1 christos } else { 6799 1.23 christos tname = qctx->fresp->foundname; 6800 1.1 christos } 6801 1.1 christos 6802 1.20 christos dns_name_copy(tname, qctx->fname); 6803 1.1 christos 6804 1.1 christos if (qctx->rpz_st != NULL && 6805 1.16 christos (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0) 6806 1.16 christos { 6807 1.23 christos qctx->rpz_st->r.r_result = qctx->fresp->result; 6808 1.1 christos result = qctx->rpz_st->q.result; 6809 1.23 christos free_fresp(qctx->client, &qctx->fresp); 6810 1.1 christos } else if (REDIRECT(qctx->client)) { 6811 1.1 christos result = qctx->client->query.redirect.result; 6812 1.1 christos } else { 6813 1.23 christos result = qctx->fresp->result; 6814 1.1 christos } 6815 1.1 christos 6816 1.3 christos qctx->resuming = true; 6817 1.1 christos 6818 1.23 christos return query_gotanswer(qctx, result); 6819 1.3 christos 6820 1.9 christos cleanup: 6821 1.23 christos return result; 6822 1.1 christos } 6823 1.1 christos 6824 1.20 christos static void 6825 1.23 christos query_hookresume(void *arg) { 6826 1.23 christos ns_hook_resume_t *rev = (ns_hook_resume_t *)arg; 6827 1.20 christos ns_hookasync_t *hctx = NULL; 6828 1.23 christos ns_client_t *client = rev->arg; 6829 1.20 christos query_ctx_t *qctx = rev->saved_qctx; 6830 1.20 christos bool canceled; 6831 1.20 christos 6832 1.20 christos CTRACE(ISC_LOG_DEBUG(3), "query_hookresume"); 6833 1.20 christos 6834 1.20 christos REQUIRE(NS_CLIENT_VALID(client)); 6835 1.20 christos 6836 1.20 christos LOCK(&client->query.fetchlock); 6837 1.20 christos if (client->query.hookactx != NULL) { 6838 1.20 christos INSIST(rev->ctx == client->query.hookactx); 6839 1.20 christos client->query.hookactx = NULL; 6840 1.20 christos canceled = false; 6841 1.23 christos client->now = isc_stdtime_now(); 6842 1.20 christos } else { 6843 1.20 christos canceled = true; 6844 1.20 christos } 6845 1.20 christos UNLOCK(&client->query.fetchlock); 6846 1.20 christos SAVE(hctx, rev->ctx); 6847 1.20 christos 6848 1.23 christos release_recursionquota(client); 6849 1.20 christos 6850 1.20 christos /* 6851 1.23 christos * The fetch handle should be detached before resuming query processing 6852 1.23 christos * below, since that may trigger another recursion or asynchronous hook 6853 1.23 christos * event. 6854 1.20 christos */ 6855 1.23 christos isc_nmhandle_detach(&HANDLE_RECTYPE_HOOK(client)); 6856 1.20 christos 6857 1.20 christos client->state = NS_CLIENTSTATE_WORKING; 6858 1.20 christos 6859 1.20 christos if (canceled) { 6860 1.20 christos /* 6861 1.20 christos * Note: unlike fetch_callback, this function doesn't bother 6862 1.20 christos * to check the 'shutdown' condition, as that doesn't seem to 6863 1.20 christos * happen in the latest implementation. 6864 1.20 christos */ 6865 1.20 christos query_error(client, DNS_R_SERVFAIL, __LINE__); 6866 1.20 christos 6867 1.20 christos /* 6868 1.20 christos * There's no other place to free/release any data maintained 6869 1.20 christos * in qctx. We need to do it here to prevent leak. 6870 1.20 christos */ 6871 1.20 christos qctx_clean(qctx); 6872 1.20 christos qctx_freedata(qctx); 6873 1.20 christos 6874 1.20 christos /* 6875 1.20 christos * As we're almost done with this client, make sure any internal 6876 1.20 christos * resource for hooks will be released (if necessary) via the 6877 1.20 christos * QCTX_DESTROYED hook. 6878 1.20 christos */ 6879 1.20 christos qctx->detach_client = true; 6880 1.20 christos } else { 6881 1.20 christos switch (rev->hookpoint) { 6882 1.20 christos case NS_QUERY_SETUP: 6883 1.23 christos query_setup(client, qctx->qtype); 6884 1.20 christos break; 6885 1.20 christos case NS_QUERY_START_BEGIN: 6886 1.20 christos (void)ns__query_start(qctx); 6887 1.20 christos break; 6888 1.20 christos case NS_QUERY_LOOKUP_BEGIN: 6889 1.20 christos (void)query_lookup(qctx); 6890 1.20 christos break; 6891 1.20 christos case NS_QUERY_RESUME_BEGIN: 6892 1.20 christos case NS_QUERY_RESUME_RESTORED: 6893 1.20 christos (void)query_resume(qctx); 6894 1.20 christos break; 6895 1.20 christos case NS_QUERY_GOT_ANSWER_BEGIN: 6896 1.20 christos (void)query_gotanswer(qctx, rev->origresult); 6897 1.20 christos break; 6898 1.20 christos case NS_QUERY_RESPOND_ANY_BEGIN: 6899 1.20 christos (void)query_respond_any(qctx); 6900 1.20 christos break; 6901 1.20 christos case NS_QUERY_ADDANSWER_BEGIN: 6902 1.20 christos (void)query_addanswer(qctx); 6903 1.20 christos break; 6904 1.20 christos case NS_QUERY_NOTFOUND_BEGIN: 6905 1.20 christos (void)query_notfound(qctx); 6906 1.20 christos break; 6907 1.20 christos case NS_QUERY_PREP_DELEGATION_BEGIN: 6908 1.20 christos (void)query_prepare_delegation_response(qctx); 6909 1.20 christos break; 6910 1.20 christos case NS_QUERY_ZONE_DELEGATION_BEGIN: 6911 1.20 christos (void)query_zone_delegation(qctx); 6912 1.20 christos break; 6913 1.20 christos case NS_QUERY_DELEGATION_BEGIN: 6914 1.20 christos (void)query_delegation(qctx); 6915 1.20 christos break; 6916 1.20 christos case NS_QUERY_DELEGATION_RECURSE_BEGIN: 6917 1.20 christos (void)query_delegation_recurse(qctx); 6918 1.20 christos break; 6919 1.20 christos case NS_QUERY_NODATA_BEGIN: 6920 1.20 christos (void)query_nodata(qctx, rev->origresult); 6921 1.20 christos break; 6922 1.20 christos case NS_QUERY_NXDOMAIN_BEGIN: 6923 1.20 christos (void)query_nxdomain(qctx, rev->origresult); 6924 1.20 christos break; 6925 1.20 christos case NS_QUERY_NCACHE_BEGIN: 6926 1.20 christos (void)query_ncache(qctx, rev->origresult); 6927 1.20 christos break; 6928 1.20 christos case NS_QUERY_CNAME_BEGIN: 6929 1.20 christos (void)query_cname(qctx); 6930 1.20 christos break; 6931 1.20 christos case NS_QUERY_DNAME_BEGIN: 6932 1.20 christos (void)query_dname(qctx); 6933 1.20 christos break; 6934 1.20 christos case NS_QUERY_RESPOND_BEGIN: 6935 1.20 christos (void)query_respond(qctx); 6936 1.20 christos break; 6937 1.20 christos case NS_QUERY_PREP_RESPONSE_BEGIN: 6938 1.20 christos (void)query_prepresponse(qctx); 6939 1.20 christos break; 6940 1.20 christos case NS_QUERY_DONE_BEGIN: 6941 1.20 christos case NS_QUERY_DONE_SEND: 6942 1.20 christos (void)ns_query_done(qctx); 6943 1.20 christos break; 6944 1.20 christos 6945 1.20 christos /* Not all hookpoints can use recursion. Catch violations */ 6946 1.20 christos case NS_QUERY_RESPOND_ANY_FOUND: /* due to side effect */ 6947 1.20 christos case NS_QUERY_NOTFOUND_RECURSE: /* in recursion */ 6948 1.20 christos case NS_QUERY_ZEROTTL_RECURSE: /* in recursion */ 6949 1.20 christos default: /* catch-all just in case */ 6950 1.20 christos INSIST(false); 6951 1.20 christos } 6952 1.20 christos } 6953 1.20 christos 6954 1.23 christos isc_mem_put(hctx->mctx, rev, sizeof(*rev)); 6955 1.20 christos hctx->destroy(&hctx); 6956 1.20 christos qctx_destroy(qctx); 6957 1.23 christos isc_mem_put(client->manager->mctx, qctx, sizeof(*qctx)); 6958 1.20 christos } 6959 1.20 christos 6960 1.20 christos isc_result_t 6961 1.20 christos ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync, 6962 1.20 christos void *arg) { 6963 1.20 christos isc_result_t result; 6964 1.20 christos ns_client_t *client = qctx->client; 6965 1.20 christos query_ctx_t *saved_qctx = NULL; 6966 1.20 christos 6967 1.20 christos CTRACE(ISC_LOG_DEBUG(3), "ns_query_hookasync"); 6968 1.20 christos 6969 1.20 christos REQUIRE(NS_CLIENT_VALID(client)); 6970 1.20 christos REQUIRE(client->query.hookactx == NULL); 6971 1.23 christos REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL); 6972 1.20 christos 6973 1.23 christos result = acquire_recursionquota(client); 6974 1.20 christos if (result != ISC_R_SUCCESS) { 6975 1.20 christos goto cleanup; 6976 1.20 christos } 6977 1.20 christos 6978 1.23 christos saved_qctx = isc_mem_get(client->manager->mctx, sizeof(*saved_qctx)); 6979 1.20 christos qctx_save(qctx, saved_qctx); 6980 1.23 christos result = runasync(saved_qctx, client->manager->mctx, arg, 6981 1.23 christos client->manager->loop, query_hookresume, client, 6982 1.23 christos &client->query.hookactx); 6983 1.20 christos if (result != ISC_R_SUCCESS) { 6984 1.23 christos goto cleanup_and_detach_from_quota; 6985 1.20 christos } 6986 1.20 christos 6987 1.24 christos /* Record that an asynchronous copy of the qctx has been started */ 6988 1.24 christos qctx->async = true; 6989 1.24 christos 6990 1.20 christos /* 6991 1.20 christos * Typically the runasync() function will trigger recursion, but 6992 1.20 christos * there is no need to set NS_QUERYATTR_RECURSING. The calling hook 6993 1.20 christos * is expected to return NS_HOOK_RETURN, and the RECURSING 6994 1.20 christos * attribute won't be checked anywhere. 6995 1.20 christos * 6996 1.20 christos * Hook-based asynchronous processing cannot coincide with normal 6997 1.23 christos * recursion. Unlike in ns_query_recurse(), we attach to the handle 6998 1.23 christos * only if 'runasync' succeeds. It should be safe since we're either in 6999 1.23 christos * the client task or pausing it. 7000 1.20 christos */ 7001 1.23 christos isc_nmhandle_attach(client->handle, &HANDLE_RECTYPE_HOOK(client)); 7002 1.23 christos return ISC_R_SUCCESS; 7003 1.20 christos 7004 1.23 christos cleanup_and_detach_from_quota: 7005 1.23 christos release_recursionquota(client); 7006 1.20 christos cleanup: 7007 1.20 christos /* 7008 1.20 christos * If we fail, send SERVFAIL now. It may be better to let the caller 7009 1.20 christos * decide what to do on failure of this function, but hooks don't have 7010 1.20 christos * access to query_error(). 7011 1.20 christos */ 7012 1.20 christos query_error(client, DNS_R_SERVFAIL, __LINE__); 7013 1.20 christos 7014 1.20 christos /* 7015 1.20 christos * Free all resource related to the query and set detach_client, 7016 1.20 christos * similar to the cancel case of query_hookresume; the callers will 7017 1.20 christos * simply return on failure of this function, so there's no other 7018 1.20 christos * place for this to prevent leak. 7019 1.20 christos */ 7020 1.20 christos if (saved_qctx != NULL) { 7021 1.20 christos qctx_clean(saved_qctx); 7022 1.20 christos qctx_freedata(saved_qctx); 7023 1.20 christos qctx_destroy(saved_qctx); 7024 1.23 christos isc_mem_put(client->manager->mctx, saved_qctx, 7025 1.23 christos sizeof(*saved_qctx)); 7026 1.20 christos } 7027 1.20 christos qctx->detach_client = true; 7028 1.23 christos return result; 7029 1.20 christos } 7030 1.20 christos 7031 1.1 christos /*% 7032 1.1 christos * If the query is recursive, check the SERVFAIL cache to see whether 7033 1.1 christos * identical queries have failed recently. If we find a match, and it was 7034 1.1 christos * from a query with CD=1, *or* if the current query has CD=0, then we just 7035 1.1 christos * return SERVFAIL again. This prevents a validation failure from eliciting a 7036 1.1 christos * SERVFAIL response to a CD=1 query. 7037 1.1 christos */ 7038 1.1 christos isc_result_t 7039 1.1 christos ns__query_sfcache(query_ctx_t *qctx) { 7040 1.23 christos isc_result_t failcache; 7041 1.3 christos uint32_t flags; 7042 1.1 christos 7043 1.1 christos /* 7044 1.1 christos * The SERVFAIL cache doesn't apply to authoritative queries. 7045 1.1 christos */ 7046 1.1 christos if (!RECURSIONOK(qctx->client)) { 7047 1.23 christos return ISC_R_COMPLETE; 7048 1.1 christos } 7049 1.1 christos 7050 1.1 christos flags = 0; 7051 1.1 christos #ifdef ENABLE_AFL 7052 1.23 christos if (qctx->client->manager->sctx->fuzztype == isc_fuzz_resolver) { 7053 1.23 christos failcache = ISC_R_NOTFOUND; 7054 1.23 christos } else 7055 1.23 christos #endif /* ifdef ENABLE_AFL */ 7056 1.23 christos { 7057 1.9 christos failcache = dns_badcache_find( 7058 1.9 christos qctx->view->failcache, qctx->client->query.qname, 7059 1.23 christos qctx->qtype, &flags, 7060 1.23 christos isc_time_seconds(&qctx->client->tnow)); 7061 1.23 christos } 7062 1.23 christos 7063 1.23 christos if (failcache != ISC_R_SUCCESS) { 7064 1.23 christos return ISC_R_COMPLETE; 7065 1.1 christos } 7066 1.23 christos 7067 1.23 christos if (((flags & NS_FAILCACHE_CD) != 0) || 7068 1.23 christos ((qctx->client->message->flags & DNS_MESSAGEFLAG_CD) == 0)) 7069 1.1 christos { 7070 1.1 christos if (isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) { 7071 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 7072 1.3 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 7073 1.1 christos 7074 1.9 christos dns_name_format(qctx->client->query.qname, namebuf, 7075 1.9 christos sizeof(namebuf)); 7076 1.3 christos dns_rdatatype_format(qctx->qtype, typebuf, 7077 1.3 christos sizeof(typebuf)); 7078 1.9 christos ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT, 7079 1.9 christos NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(1), 7080 1.9 christos "servfail cache hit %s/%s (%s)", namebuf, 7081 1.9 christos typebuf, 7082 1.9 christos ((flags & NS_FAILCACHE_CD) != 0) ? "CD=1" 7083 1.9 christos : "CD=" 7084 1.9 christos "0"); 7085 1.1 christos } 7086 1.1 christos 7087 1.1 christos qctx->client->attributes |= NS_CLIENTATTR_NOSETFC; 7088 1.1 christos QUERY_ERROR(qctx, DNS_R_SERVFAIL); 7089 1.23 christos return ns_query_done(qctx); 7090 1.23 christos } 7091 1.23 christos 7092 1.23 christos return ISC_R_COMPLETE; 7093 1.23 christos } 7094 1.23 christos 7095 1.23 christos static void 7096 1.23 christos query_trace_rrldrop(query_ctx_t *qctx, 7097 1.23 christos dns_rrl_result_t rrl_result ISC_ATTR_UNUSED) { 7098 1.23 christos if (!LIBNS_RRL_DROP_ENABLED()) { 7099 1.23 christos return; 7100 1.1 christos } 7101 1.1 christos 7102 1.23 christos char peerbuf[ISC_SOCKADDR_FORMATSIZE]; 7103 1.23 christos isc_netaddr_t peer; 7104 1.23 christos isc_netaddr_fromsockaddr(&peer, &qctx->client->peeraddr); 7105 1.23 christos isc_netaddr_format(&peer, peerbuf, sizeof(peerbuf)); 7106 1.23 christos 7107 1.23 christos char qnamebuf[DNS_NAME_FORMATSIZE]; 7108 1.23 christos char fnamebuf[DNS_NAME_FORMATSIZE]; 7109 1.23 christos dns_name_format(qctx->client->query.qname, qnamebuf, sizeof(qnamebuf)); 7110 1.23 christos dns_name_format(qctx->fname, fnamebuf, sizeof(fnamebuf)); 7111 1.23 christos LIBNS_RRL_DROP(peerbuf, qnamebuf, fnamebuf, rrl_result); 7112 1.1 christos } 7113 1.1 christos 7114 1.1 christos /*% 7115 1.1 christos * Handle response rate limiting (RRL). 7116 1.1 christos */ 7117 1.1 christos static isc_result_t 7118 1.1 christos query_checkrrl(query_ctx_t *qctx, isc_result_t result) { 7119 1.1 christos /* 7120 1.1 christos * Rate limit these responses to this client. 7121 1.1 christos * Do not delay counting and handling obvious referrals, 7122 1.1 christos * since those won't come here again. 7123 1.1 christos * Delay handling delegations for which we are certain to recurse and 7124 1.1 christos * return here (DNS_R_DELEGATION, not a child of one of our 7125 1.1 christos * own zones, and recursion enabled) 7126 1.1 christos * Don't mess with responses rewritten by RPZ 7127 1.1 christos * Count each response at most once. 7128 1.1 christos */ 7129 1.3 christos 7130 1.3 christos /* 7131 1.3 christos * XXXMPA the rrl system tests fails sometimes and RRL_CHECKED 7132 1.3 christos * is set when we are called the second time preventing the 7133 1.3 christos * response being dropped. 7134 1.3 christos */ 7135 1.9 christos ns_client_log( 7136 1.9 christos qctx->client, DNS_LOGCATEGORY_RRL, NS_LOGMODULE_QUERY, 7137 1.9 christos ISC_LOG_DEBUG(99), 7138 1.9 christos "rrl=%p, HAVECOOKIE=%u, result=%s, " 7139 1.9 christos "fname=%p(%u), is_zone=%u, RECURSIONOK=%u, " 7140 1.23 christos "query.rpz_st=%p(%u), RRL_CHECKED=%u", 7141 1.9 christos qctx->client->view->rrl, HAVECOOKIE(qctx->client), 7142 1.9 christos isc_result_toid(result), qctx->fname, 7143 1.9 christos qctx->fname != NULL ? dns_name_isabsolute(qctx->fname) : 0, 7144 1.9 christos qctx->is_zone, RECURSIONOK(qctx->client), 7145 1.9 christos qctx->client->query.rpz_st, 7146 1.9 christos qctx->client->query.rpz_st != NULL 7147 1.9 christos ? ((qctx->client->query.rpz_st->state & 7148 1.9 christos DNS_RPZ_REWRITTEN) != 0) 7149 1.9 christos : 0, 7150 1.9 christos (qctx->client->query.attributes & NS_QUERYATTR_RRL_CHECKED) != 7151 1.9 christos 0); 7152 1.3 christos 7153 1.9 christos if (qctx->view->rrl != NULL && !HAVECOOKIE(qctx->client) && 7154 1.1 christos ((qctx->fname != NULL && dns_name_isabsolute(qctx->fname)) || 7155 1.1 christos (result == ISC_R_NOTFOUND && !RECURSIONOK(qctx->client))) && 7156 1.9 christos !(result == DNS_R_DELEGATION && !qctx->is_zone && 7157 1.9 christos RECURSIONOK(qctx->client)) && 7158 1.1 christos (qctx->client->query.rpz_st == NULL || 7159 1.1 christos (qctx->client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) && 7160 1.1 christos (qctx->client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0) 7161 1.1 christos { 7162 1.1 christos dns_rdataset_t nc_rdataset; 7163 1.3 christos bool wouldlog; 7164 1.1 christos dns_fixedname_t fixed; 7165 1.1 christos const dns_name_t *constname; 7166 1.1 christos char log_buf[DNS_RRL_LOG_BUF_LEN]; 7167 1.1 christos isc_result_t nc_result, resp_result; 7168 1.1 christos dns_rrl_result_t rrl_result; 7169 1.1 christos 7170 1.1 christos qctx->client->query.attributes |= NS_QUERYATTR_RRL_CHECKED; 7171 1.1 christos 7172 1.1 christos wouldlog = isc_log_wouldlog(ns_lctx, DNS_RRL_LOG_DROP); 7173 1.1 christos constname = qctx->fname; 7174 1.1 christos if (result == DNS_R_NXDOMAIN) { 7175 1.1 christos /* 7176 1.1 christos * Use the database origin name to rate limit NXDOMAIN 7177 1.1 christos */ 7178 1.9 christos if (qctx->db != NULL) { 7179 1.1 christos constname = dns_db_origin(qctx->db); 7180 1.9 christos } 7181 1.1 christos resp_result = result; 7182 1.1 christos } else if (result == DNS_R_NCACHENXDOMAIN && 7183 1.1 christos qctx->rdataset != NULL && 7184 1.1 christos dns_rdataset_isassociated(qctx->rdataset) && 7185 1.1 christos (qctx->rdataset->attributes & 7186 1.9 christos DNS_RDATASETATTR_NEGATIVE) != 0) 7187 1.9 christos { 7188 1.1 christos /* 7189 1.1 christos * Try to use owner name in the negative cache SOA. 7190 1.1 christos */ 7191 1.1 christos dns_fixedname_init(&fixed); 7192 1.1 christos dns_rdataset_init(&nc_rdataset); 7193 1.1 christos for (nc_result = dns_rdataset_first(qctx->rdataset); 7194 1.1 christos nc_result == ISC_R_SUCCESS; 7195 1.1 christos nc_result = dns_rdataset_next(qctx->rdataset)) 7196 1.1 christos { 7197 1.1 christos dns_ncache_current(qctx->rdataset, 7198 1.1 christos dns_fixedname_name(&fixed), 7199 1.1 christos &nc_rdataset); 7200 1.1 christos if (nc_rdataset.type == dns_rdatatype_soa) { 7201 1.1 christos dns_rdataset_disassociate(&nc_rdataset); 7202 1.1 christos constname = dns_fixedname_name(&fixed); 7203 1.1 christos break; 7204 1.1 christos } 7205 1.1 christos dns_rdataset_disassociate(&nc_rdataset); 7206 1.1 christos } 7207 1.1 christos resp_result = DNS_R_NXDOMAIN; 7208 1.9 christos } else if (result == DNS_R_NXRRSET || result == DNS_R_EMPTYNAME) 7209 1.9 christos { 7210 1.1 christos resp_result = DNS_R_NXRRSET; 7211 1.1 christos } else if (result == DNS_R_DELEGATION) { 7212 1.1 christos resp_result = result; 7213 1.1 christos } else if (result == ISC_R_NOTFOUND) { 7214 1.1 christos /* 7215 1.1 christos * Handle referral to ".", including when recursion 7216 1.1 christos * is off or not requested and the hints have not 7217 1.20 christos * been loaded. 7218 1.1 christos */ 7219 1.1 christos constname = dns_rootname; 7220 1.1 christos resp_result = DNS_R_DELEGATION; 7221 1.1 christos } else { 7222 1.1 christos resp_result = ISC_R_SUCCESS; 7223 1.1 christos } 7224 1.1 christos 7225 1.9 christos rrl_result = dns_rrl( 7226 1.15 christos qctx->view, qctx->zone, &qctx->client->peeraddr, 7227 1.15 christos TCP(qctx->client), qctx->client->message->rdclass, 7228 1.15 christos qctx->qtype, constname, resp_result, qctx->client->now, 7229 1.15 christos wouldlog, log_buf, sizeof(log_buf)); 7230 1.1 christos if (rrl_result != DNS_RRL_RESULT_OK) { 7231 1.1 christos /* 7232 1.26 christos * Log dropped or slipped responses in the query-errors 7233 1.1 christos * category so that requests are not silently lost. 7234 1.1 christos * Starts of rate-limited bursts are logged in 7235 1.1 christos * DNS_LOGCATEGORY_RRL. 7236 1.1 christos * 7237 1.1 christos * Dropped responses are counted with dropped queries 7238 1.1 christos * in QryDropped while slipped responses are counted 7239 1.1 christos * with other truncated responses in RespTruncated. 7240 1.1 christos */ 7241 1.1 christos if (wouldlog) { 7242 1.26 christos ns_client_log(qctx->client, 7243 1.26 christos NS_LOGCATEGORY_QUERY_ERRORS, 7244 1.1 christos NS_LOGMODULE_QUERY, 7245 1.9 christos DNS_RRL_LOG_DROP, "%s", log_buf); 7246 1.1 christos } 7247 1.1 christos 7248 1.23 christos /* 7249 1.23 christos * If tracing is enabled, format some extra information 7250 1.23 christos * to pass along. 7251 1.23 christos */ 7252 1.23 christos query_trace_rrldrop(qctx, rrl_result); 7253 1.23 christos 7254 1.3 christos if (!qctx->view->rrl->log_only) { 7255 1.1 christos if (rrl_result == DNS_RRL_RESULT_DROP) { 7256 1.1 christos /* 7257 1.1 christos * These will also be counted in 7258 1.1 christos * ns_statscounter_dropped 7259 1.1 christos */ 7260 1.1 christos inc_stats(qctx->client, 7261 1.9 christos ns_statscounter_ratedropped); 7262 1.1 christos QUERY_ERROR(qctx, DNS_R_DROP); 7263 1.1 christos } else { 7264 1.1 christos /* 7265 1.1 christos * These will also be counted in 7266 1.1 christos * ns_statscounter_truncatedresp 7267 1.1 christos */ 7268 1.1 christos inc_stats(qctx->client, 7269 1.9 christos ns_statscounter_rateslipped); 7270 1.1 christos if (WANTCOOKIE(qctx->client)) { 7271 1.1 christos qctx->client->message->flags &= 7272 1.1 christos ~DNS_MESSAGEFLAG_AA; 7273 1.1 christos qctx->client->message->flags &= 7274 1.1 christos ~DNS_MESSAGEFLAG_AD; 7275 1.1 christos qctx->client->message->rcode = 7276 1.9 christos dns_rcode_badcookie; 7277 1.1 christos } else { 7278 1.1 christos qctx->client->message->flags |= 7279 1.1 christos DNS_MESSAGEFLAG_TC; 7280 1.1 christos if (resp_result == 7281 1.16 christos DNS_R_NXDOMAIN) 7282 1.16 christos { 7283 1.9 christos qctx->client->message 7284 1.9 christos ->rcode = 7285 1.9 christos dns_rcode_nxdomain; 7286 1.1 christos } 7287 1.1 christos } 7288 1.1 christos } 7289 1.23 christos return DNS_R_DROP; 7290 1.1 christos } 7291 1.1 christos } 7292 1.1 christos } 7293 1.1 christos 7294 1.23 christos return ISC_R_SUCCESS; 7295 1.1 christos } 7296 1.1 christos 7297 1.26 christos static void 7298 1.26 christos query_rpz_add_ede(query_ctx_t *qctx) { 7299 1.26 christos if (qctx->rpz_st->m.rpz->ede != 0 && 7300 1.26 christos qctx->rpz_st->m.rpz->ede != UINT16_MAX) 7301 1.26 christos { 7302 1.26 christos dns_ede_add(&qctx->client->edectx, qctx->rpz_st->m.rpz->ede, 7303 1.26 christos NULL); 7304 1.26 christos } 7305 1.26 christos } 7306 1.26 christos 7307 1.1 christos /*% 7308 1.1 christos * Do any RPZ rewriting that may be needed for this query. 7309 1.1 christos */ 7310 1.1 christos static isc_result_t 7311 1.1 christos query_checkrpz(query_ctx_t *qctx, isc_result_t result) { 7312 1.1 christos isc_result_t rresult; 7313 1.1 christos 7314 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_checkrpz"); 7315 1.9 christos 7316 1.9 christos rresult = rpz_rewrite(qctx->client, qctx->qtype, result, qctx->resuming, 7317 1.1 christos qctx->rdataset, qctx->sigrdataset); 7318 1.1 christos qctx->rpz_st = qctx->client->query.rpz_st; 7319 1.1 christos switch (rresult) { 7320 1.1 christos case ISC_R_SUCCESS: 7321 1.1 christos break; 7322 1.13 christos case ISC_R_NOTFOUND: 7323 1.1 christos case DNS_R_DISALLOWED: 7324 1.23 christos return result; 7325 1.1 christos case DNS_R_DELEGATION: 7326 1.1 christos /* 7327 1.1 christos * recursing for NS names or addresses, 7328 1.1 christos * so save the main query state 7329 1.1 christos */ 7330 1.13 christos INSIST(!RECURSING(qctx->client)); 7331 1.1 christos qctx->rpz_st->q.qtype = qctx->qtype; 7332 1.1 christos qctx->rpz_st->q.is_zone = qctx->is_zone; 7333 1.1 christos qctx->rpz_st->q.authoritative = qctx->authoritative; 7334 1.1 christos SAVE(qctx->rpz_st->q.zone, qctx->zone); 7335 1.1 christos SAVE(qctx->rpz_st->q.db, qctx->db); 7336 1.1 christos SAVE(qctx->rpz_st->q.node, qctx->node); 7337 1.1 christos SAVE(qctx->rpz_st->q.rdataset, qctx->rdataset); 7338 1.1 christos SAVE(qctx->rpz_st->q.sigrdataset, qctx->sigrdataset); 7339 1.20 christos dns_name_copy(qctx->fname, qctx->rpz_st->fname); 7340 1.1 christos qctx->rpz_st->q.result = result; 7341 1.1 christos qctx->client->query.attributes |= NS_QUERYATTR_RECURSING; 7342 1.23 christos return ISC_R_COMPLETE; 7343 1.1 christos default: 7344 1.3 christos QUERY_ERROR(qctx, rresult); 7345 1.23 christos return ISC_R_COMPLETE; 7346 1.1 christos } 7347 1.1 christos 7348 1.1 christos if (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS) { 7349 1.1 christos qctx->rpz_st->state |= DNS_RPZ_REWRITTEN; 7350 1.1 christos } 7351 1.1 christos 7352 1.1 christos if (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS && 7353 1.1 christos qctx->rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU && 7354 1.1 christos (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_TCP_ONLY || 7355 1.1 christos !TCP(qctx->client)) && 7356 1.1 christos qctx->rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) 7357 1.1 christos { 7358 1.1 christos /* 7359 1.1 christos * We got a hit and are going to answer with our 7360 1.1 christos * fiction. Ensure that we answer with the name 7361 1.1 christos * we looked up even if we were stopped short 7362 1.1 christos * in recursion or for a deferral. 7363 1.1 christos */ 7364 1.20 christos dns_name_copy(qctx->client->query.qname, qctx->fname); 7365 1.1 christos rpz_clean(&qctx->zone, &qctx->db, &qctx->node, NULL); 7366 1.1 christos if (qctx->rpz_st->m.rdataset != NULL) { 7367 1.3 christos ns_client_putrdataset(qctx->client, &qctx->rdataset); 7368 1.1 christos RESTORE(qctx->rdataset, qctx->rpz_st->m.rdataset); 7369 1.1 christos } else { 7370 1.1 christos qctx_clean(qctx); 7371 1.1 christos } 7372 1.1 christos qctx->version = NULL; 7373 1.1 christos 7374 1.1 christos RESTORE(qctx->node, qctx->rpz_st->m.node); 7375 1.1 christos RESTORE(qctx->db, qctx->rpz_st->m.db); 7376 1.1 christos RESTORE(qctx->version, qctx->rpz_st->m.version); 7377 1.1 christos RESTORE(qctx->zone, qctx->rpz_st->m.zone); 7378 1.1 christos 7379 1.1 christos /* 7380 1.1 christos * Add SOA record to additional section 7381 1.1 christos */ 7382 1.5 christos if (qctx->rpz_st->m.rpz->addsoa) { 7383 1.22 christos rresult = query_addsoa(qctx, UINT32_MAX, 7384 1.5 christos DNS_SECTION_ADDITIONAL); 7385 1.5 christos if (rresult != ISC_R_SUCCESS) { 7386 1.5 christos QUERY_ERROR(qctx, result); 7387 1.23 christos return ISC_R_COMPLETE; 7388 1.5 christos } 7389 1.1 christos } 7390 1.1 christos 7391 1.1 christos switch (qctx->rpz_st->m.policy) { 7392 1.1 christos case DNS_RPZ_POLICY_TCP_ONLY: 7393 1.1 christos qctx->client->message->flags |= DNS_MESSAGEFLAG_TC; 7394 1.1 christos if (result == DNS_R_NXDOMAIN || 7395 1.16 christos result == DNS_R_NCACHENXDOMAIN) 7396 1.16 christos { 7397 1.1 christos qctx->client->message->rcode = 7398 1.9 christos dns_rcode_nxdomain; 7399 1.9 christos } 7400 1.3 christos rpz_log_rewrite(qctx->client, false, 7401 1.1 christos qctx->rpz_st->m.policy, 7402 1.1 christos qctx->rpz_st->m.type, qctx->zone, 7403 1.1 christos qctx->rpz_st->p_name, NULL, 7404 1.1 christos qctx->rpz_st->m.rpz->num); 7405 1.23 christos return ISC_R_COMPLETE; 7406 1.1 christos case DNS_RPZ_POLICY_DROP: 7407 1.1 christos QUERY_ERROR(qctx, DNS_R_DROP); 7408 1.3 christos rpz_log_rewrite(qctx->client, false, 7409 1.1 christos qctx->rpz_st->m.policy, 7410 1.1 christos qctx->rpz_st->m.type, qctx->zone, 7411 1.1 christos qctx->rpz_st->p_name, NULL, 7412 1.1 christos qctx->rpz_st->m.rpz->num); 7413 1.23 christos return ISC_R_COMPLETE; 7414 1.1 christos case DNS_RPZ_POLICY_NXDOMAIN: 7415 1.1 christos result = DNS_R_NXDOMAIN; 7416 1.3 christos qctx->nxrewrite = true; 7417 1.3 christos qctx->rpz = true; 7418 1.1 christos break; 7419 1.1 christos case DNS_RPZ_POLICY_NODATA: 7420 1.6 christos qctx->nxrewrite = true; 7421 1.15 christos FALLTHROUGH; 7422 1.6 christos case DNS_RPZ_POLICY_DNS64: 7423 1.1 christos result = DNS_R_NXRRSET; 7424 1.3 christos qctx->rpz = true; 7425 1.1 christos break; 7426 1.1 christos case DNS_RPZ_POLICY_RECORD: 7427 1.1 christos result = qctx->rpz_st->m.result; 7428 1.1 christos if (qctx->qtype == dns_rdatatype_any && 7429 1.16 christos result != DNS_R_CNAME) 7430 1.16 christos { 7431 1.1 christos /* 7432 1.1 christos * We will add all of the rdatasets of 7433 1.1 christos * the node by iterating later, 7434 1.1 christos * and set the TTL then. 7435 1.1 christos */ 7436 1.9 christos if (dns_rdataset_isassociated(qctx->rdataset)) { 7437 1.9 christos dns_rdataset_disassociate( 7438 1.9 christos qctx->rdataset); 7439 1.9 christos } 7440 1.1 christos } else { 7441 1.1 christos /* 7442 1.1 christos * We will add this rdataset. 7443 1.1 christos */ 7444 1.1 christos qctx->rdataset->ttl = 7445 1.1 christos ISC_MIN(qctx->rdataset->ttl, 7446 1.1 christos qctx->rpz_st->m.ttl); 7447 1.1 christos } 7448 1.3 christos qctx->rpz = true; 7449 1.1 christos break; 7450 1.1 christos case DNS_RPZ_POLICY_WILDCNAME: { 7451 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 7452 1.1 christos dns_rdata_cname_t cname; 7453 1.1 christos result = dns_rdataset_first(qctx->rdataset); 7454 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 7455 1.1 christos dns_rdataset_current(qctx->rdataset, &rdata); 7456 1.9 christos result = dns_rdata_tostruct(&rdata, &cname, NULL); 7457 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 7458 1.1 christos dns_rdata_reset(&rdata); 7459 1.26 christos 7460 1.26 christos query_rpz_add_ede(qctx); 7461 1.1 christos result = query_rpzcname(qctx, &cname.cname); 7462 1.9 christos if (result != ISC_R_SUCCESS) { 7463 1.23 christos return ISC_R_COMPLETE; 7464 1.9 christos } 7465 1.1 christos qctx->fname = NULL; 7466 1.3 christos qctx->want_restart = true; 7467 1.23 christos return ISC_R_COMPLETE; 7468 1.1 christos } 7469 1.1 christos case DNS_RPZ_POLICY_CNAME: 7470 1.1 christos /* 7471 1.9 christos * Add overriding CNAME from a named.conf 7472 1.1 christos * response-policy statement 7473 1.1 christos */ 7474 1.26 christos query_rpz_add_ede(qctx); 7475 1.1 christos result = query_rpzcname(qctx, 7476 1.1 christos &qctx->rpz_st->m.rpz->cname); 7477 1.9 christos if (result != ISC_R_SUCCESS) { 7478 1.23 christos return ISC_R_COMPLETE; 7479 1.9 christos } 7480 1.1 christos qctx->fname = NULL; 7481 1.3 christos qctx->want_restart = true; 7482 1.23 christos return ISC_R_COMPLETE; 7483 1.1 christos default: 7484 1.15 christos UNREACHABLE(); 7485 1.1 christos } 7486 1.1 christos 7487 1.26 christos query_rpz_add_ede(qctx); 7488 1.23 christos 7489 1.1 christos /* 7490 1.1 christos * Turn off DNSSEC because the results of a 7491 1.1 christos * response policy zone cannot verify. 7492 1.1 christos */ 7493 1.1 christos qctx->client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC | 7494 1.1 christos NS_CLIENTATTR_WANTAD); 7495 1.1 christos qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD; 7496 1.3 christos ns_client_putrdataset(qctx->client, &qctx->sigrdataset); 7497 1.1 christos qctx->rpz_st->q.is_zone = qctx->is_zone; 7498 1.3 christos qctx->is_zone = true; 7499 1.9 christos rpz_log_rewrite(qctx->client, false, qctx->rpz_st->m.policy, 7500 1.1 christos qctx->rpz_st->m.type, qctx->zone, 7501 1.1 christos qctx->rpz_st->p_name, NULL, 7502 1.1 christos qctx->rpz_st->m.rpz->num); 7503 1.1 christos } 7504 1.1 christos 7505 1.23 christos return result; 7506 1.1 christos } 7507 1.1 christos 7508 1.1 christos /*% 7509 1.1 christos * Add a CNAME to a query response, including translating foo.evil.com and 7510 1.1 christos * *.evil.com CNAME *.example.com 7511 1.1 christos * to 7512 1.1 christos * foo.evil.com CNAME foo.evil.com.example.com 7513 1.1 christos */ 7514 1.1 christos static isc_result_t 7515 1.1 christos query_rpzcname(query_ctx_t *qctx, dns_name_t *cname) { 7516 1.6 christos ns_client_t *client; 7517 1.1 christos dns_fixedname_t prefix, suffix; 7518 1.1 christos unsigned int labels; 7519 1.1 christos isc_result_t result; 7520 1.1 christos 7521 1.6 christos REQUIRE(qctx != NULL && qctx->client != NULL); 7522 1.6 christos 7523 1.6 christos client = qctx->client; 7524 1.6 christos 7525 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_rpzcname"); 7526 1.1 christos 7527 1.1 christos labels = dns_name_countlabels(cname); 7528 1.1 christos if (labels > 2 && dns_name_iswildcard(cname)) { 7529 1.1 christos dns_fixedname_init(&prefix); 7530 1.1 christos dns_name_split(client->query.qname, 1, 7531 1.1 christos dns_fixedname_name(&prefix), NULL); 7532 1.1 christos dns_fixedname_init(&suffix); 7533 1.9 christos dns_name_split(cname, labels - 1, NULL, 7534 1.9 christos dns_fixedname_name(&suffix)); 7535 1.1 christos result = dns_name_concatenate(dns_fixedname_name(&prefix), 7536 1.1 christos dns_fixedname_name(&suffix), 7537 1.1 christos qctx->fname, NULL); 7538 1.1 christos if (result == DNS_R_NAMETOOLONG) { 7539 1.1 christos client->message->rcode = dns_rcode_yxdomain; 7540 1.1 christos } else if (result != ISC_R_SUCCESS) { 7541 1.23 christos return result; 7542 1.1 christos } 7543 1.1 christos } else { 7544 1.20 christos dns_name_copy(cname, qctx->fname); 7545 1.1 christos } 7546 1.1 christos 7547 1.3 christos ns_client_keepname(client, qctx->fname, qctx->dbuf); 7548 1.23 christos query_addcname(qctx, dns_trust_authanswer, qctx->rpz_st->m.ttl); 7549 1.1 christos 7550 1.3 christos rpz_log_rewrite(client, false, qctx->rpz_st->m.policy, 7551 1.1 christos qctx->rpz_st->m.type, qctx->rpz_st->m.zone, 7552 1.1 christos qctx->rpz_st->p_name, qctx->fname, 7553 1.1 christos qctx->rpz_st->m.rpz->num); 7554 1.1 christos 7555 1.1 christos ns_client_qnamereplace(client, qctx->fname); 7556 1.1 christos 7557 1.1 christos /* 7558 1.1 christos * Turn off DNSSEC because the results of a 7559 1.1 christos * response policy zone cannot verify. 7560 1.1 christos */ 7561 1.1 christos client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC | 7562 1.1 christos NS_CLIENTATTR_WANTAD); 7563 1.1 christos 7564 1.23 christos return ISC_R_SUCCESS; 7565 1.1 christos } 7566 1.1 christos 7567 1.1 christos /*% 7568 1.1 christos * Check the configured trust anchors for a root zone trust anchor 7569 1.1 christos * with a key id that matches qctx->client->query.root_key_sentinel_keyid. 7570 1.1 christos * 7571 1.3 christos * Return true when found, otherwise return false. 7572 1.1 christos */ 7573 1.3 christos static bool 7574 1.1 christos has_ta(query_ctx_t *qctx) { 7575 1.1 christos dns_keytable_t *keytable = NULL; 7576 1.1 christos dns_keynode_t *keynode = NULL; 7577 1.10 christos dns_rdataset_t dsset; 7578 1.9 christos dns_keytag_t sentinel = qctx->client->query.root_key_sentinel_keyid; 7579 1.1 christos isc_result_t result; 7580 1.1 christos 7581 1.3 christos result = dns_view_getsecroots(qctx->view, &keytable); 7582 1.1 christos if (result != ISC_R_SUCCESS) { 7583 1.23 christos return false; 7584 1.1 christos } 7585 1.1 christos 7586 1.1 christos result = dns_keytable_find(keytable, dns_rootname, &keynode); 7587 1.9 christos if (result != ISC_R_SUCCESS) { 7588 1.9 christos if (keynode != NULL) { 7589 1.23 christos dns_keynode_detach(&keynode); 7590 1.1 christos } 7591 1.9 christos dns_keytable_detach(&keytable); 7592 1.23 christos return false; 7593 1.9 christos } 7594 1.9 christos 7595 1.10 christos dns_rdataset_init(&dsset); 7596 1.10 christos if (dns_keynode_dsset(keynode, &dsset)) { 7597 1.10 christos for (result = dns_rdataset_first(&dsset); 7598 1.10 christos result == ISC_R_SUCCESS; 7599 1.10 christos result = dns_rdataset_next(&dsset)) 7600 1.9 christos { 7601 1.9 christos dns_rdata_t rdata = DNS_RDATA_INIT; 7602 1.9 christos dns_rdata_ds_t ds; 7603 1.9 christos 7604 1.9 christos dns_rdata_reset(&rdata); 7605 1.10 christos dns_rdataset_current(&dsset, &rdata); 7606 1.9 christos result = dns_rdata_tostruct(&rdata, &ds, NULL); 7607 1.9 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 7608 1.9 christos if (ds.key_tag == sentinel) { 7609 1.23 christos dns_keynode_detach(&keynode); 7610 1.9 christos dns_keytable_detach(&keytable); 7611 1.10 christos dns_rdataset_disassociate(&dsset); 7612 1.23 christos return true; 7613 1.9 christos } 7614 1.9 christos } 7615 1.10 christos dns_rdataset_disassociate(&dsset); 7616 1.9 christos } 7617 1.9 christos 7618 1.9 christos if (keynode != NULL) { 7619 1.23 christos dns_keynode_detach(&keynode); 7620 1.1 christos } 7621 1.9 christos 7622 1.1 christos dns_keytable_detach(&keytable); 7623 1.1 christos 7624 1.23 christos return false; 7625 1.1 christos } 7626 1.1 christos 7627 1.1 christos /*% 7628 1.1 christos * Check if a root key sentinel SERVFAIL should be returned. 7629 1.1 christos */ 7630 1.3 christos static bool 7631 1.1 christos root_key_sentinel_return_servfail(query_ctx_t *qctx, isc_result_t result) { 7632 1.1 christos /* 7633 1.1 christos * Are we looking at a "root-key-sentinel" query? 7634 1.1 christos */ 7635 1.1 christos if (!qctx->client->query.root_key_sentinel_is_ta && 7636 1.1 christos !qctx->client->query.root_key_sentinel_not_ta) 7637 1.1 christos { 7638 1.23 christos return false; 7639 1.1 christos } 7640 1.1 christos 7641 1.1 christos /* 7642 1.1 christos * We only care about the query if 'result' indicates we have a cached 7643 1.1 christos * answer. 7644 1.1 christos */ 7645 1.1 christos switch (result) { 7646 1.1 christos case ISC_R_SUCCESS: 7647 1.1 christos case DNS_R_CNAME: 7648 1.1 christos case DNS_R_DNAME: 7649 1.1 christos case DNS_R_NCACHENXDOMAIN: 7650 1.1 christos case DNS_R_NCACHENXRRSET: 7651 1.1 christos break; 7652 1.1 christos default: 7653 1.23 christos return false; 7654 1.1 christos } 7655 1.1 christos 7656 1.1 christos /* 7657 1.1 christos * Do we meet the specified conditions to return SERVFAIL? 7658 1.1 christos */ 7659 1.9 christos if (!qctx->is_zone && qctx->rdataset->trust == dns_trust_secure && 7660 1.1 christos ((qctx->client->query.root_key_sentinel_is_ta && !has_ta(qctx)) || 7661 1.1 christos (qctx->client->query.root_key_sentinel_not_ta && has_ta(qctx)))) 7662 1.1 christos { 7663 1.23 christos return true; 7664 1.1 christos } 7665 1.1 christos 7666 1.1 christos /* 7667 1.1 christos * As special processing may only be triggered by the original QNAME, 7668 1.1 christos * disable it after following a CNAME/DNAME. 7669 1.1 christos */ 7670 1.3 christos qctx->client->query.root_key_sentinel_is_ta = false; 7671 1.3 christos qctx->client->query.root_key_sentinel_not_ta = false; 7672 1.1 christos 7673 1.23 christos return false; 7674 1.1 christos } 7675 1.1 christos 7676 1.1 christos /*% 7677 1.3 christos * If serving stale answers is allowed, set up 'qctx' to look for one and 7678 1.3 christos * return true; otherwise, return false. 7679 1.3 christos */ 7680 1.3 christos static bool 7681 1.13 christos query_usestale(query_ctx_t *qctx, isc_result_t result) { 7682 1.13 christos if ((qctx->client->query.dboptions & DNS_DBFIND_STALEOK) != 0) { 7683 1.13 christos /* 7684 1.13 christos * Query was already using stale, if that didn't work the 7685 1.13 christos * last time, it won't work this time either. 7686 1.13 christos */ 7687 1.23 christos return false; 7688 1.17 christos } 7689 1.17 christos 7690 1.23 christos if (result == DNS_R_DUPLICATE || result == DNS_R_DROP) { 7691 1.15 christos /* 7692 1.15 christos * Don't enable serve-stale if the result signals a duplicate 7693 1.23 christos * query or query that is being dropped. 7694 1.15 christos */ 7695 1.23 christos return false; 7696 1.15 christos } 7697 1.15 christos 7698 1.3 christos qctx_clean(qctx); 7699 1.3 christos qctx_freedata(qctx); 7700 1.3 christos 7701 1.11 christos if (dns_view_staleanswerenabled(qctx->client->view)) { 7702 1.20 christos isc_result_t ret; 7703 1.20 christos ret = query_getdb(qctx->client, qctx->client->query.qname, 7704 1.20 christos qctx->client->query.qtype, qctx->options, 7705 1.20 christos &qctx->zone, &qctx->db, &qctx->version, 7706 1.20 christos &qctx->is_zone); 7707 1.20 christos if (ret != ISC_R_SUCCESS) { 7708 1.20 christos /* 7709 1.20 christos * Failed to get the database, unexpected, but let us 7710 1.20 christos * at least abandon serve-stale. 7711 1.20 christos */ 7712 1.23 christos return false; 7713 1.20 christos } 7714 1.20 christos 7715 1.3 christos qctx->client->query.dboptions |= DNS_DBFIND_STALEOK; 7716 1.23 christos if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL) { 7717 1.23 christos dns_resolver_destroyfetch( 7718 1.23 christos &FETCH_RECTYPE_NORMAL(qctx->client)); 7719 1.3 christos } 7720 1.11 christos 7721 1.13 christos /* 7722 1.13 christos * Start the stale-refresh-time window in case there was a 7723 1.13 christos * resolver query timeout. 7724 1.13 christos */ 7725 1.13 christos if (qctx->resuming && result == ISC_R_TIMEDOUT) { 7726 1.13 christos qctx->client->query.dboptions |= DNS_DBFIND_STALESTART; 7727 1.13 christos } 7728 1.23 christos return true; 7729 1.3 christos } 7730 1.3 christos 7731 1.23 christos return false; 7732 1.3 christos } 7733 1.3 christos 7734 1.3 christos /*% 7735 1.3 christos * Continue after doing a database lookup or returning from 7736 1.3 christos * recursion, and call out to the next function depending on the 7737 1.3 christos * result from the search. 7738 1.1 christos */ 7739 1.1 christos static isc_result_t 7740 1.18 christos query_gotanswer(query_ctx_t *qctx, isc_result_t result) { 7741 1.1 christos char errmsg[256]; 7742 1.1 christos 7743 1.1 christos CCTRACE(ISC_LOG_DEBUG(3), "query_gotanswer"); 7744 1.1 christos 7745 1.3 christos CALL_HOOK(NS_QUERY_GOT_ANSWER_BEGIN, qctx); 7746 1.3 christos 7747 1.1 christos if (query_checkrrl(qctx, result) != ISC_R_SUCCESS) { 7748 1.23 christos return ns_query_done(qctx); 7749 1.1 christos } 7750 1.1 christos 7751 1.13 christos if (!dns_name_equal(qctx->client->query.qname, dns_rootname)) { 7752 1.1 christos result = query_checkrpz(qctx, result); 7753 1.13 christos if (result == ISC_R_NOTFOUND) { 7754 1.13 christos /* 7755 1.13 christos * RPZ not configured for this view. 7756 1.13 christos */ 7757 1.13 christos goto root_key_sentinel; 7758 1.13 christos } 7759 1.13 christos if (RECURSING(qctx->client) && result == DNS_R_DISALLOWED) { 7760 1.13 christos /* 7761 1.13 christos * We are recursing, and thus RPZ processing is not 7762 1.13 christos * allowed at the moment. This could happen on a 7763 1.13 christos * "stale-answer-client-timeout" lookup. In this case, 7764 1.13 christos * bail out and wait for recursion to complete, as we 7765 1.13 christos * we can't perform the RPZ rewrite rules. 7766 1.13 christos */ 7767 1.23 christos return result; 7768 1.13 christos } 7769 1.3 christos if (result == ISC_R_COMPLETE) { 7770 1.23 christos return ns_query_done(qctx); 7771 1.3 christos } 7772 1.1 christos } 7773 1.1 christos 7774 1.13 christos root_key_sentinel: 7775 1.1 christos /* 7776 1.1 christos * If required, handle special "root-key-sentinel-is-ta-<keyid>" and 7777 1.1 christos * "root-key-sentinel-not-ta-<keyid>" labels by returning SERVFAIL. 7778 1.1 christos */ 7779 1.1 christos if (root_key_sentinel_return_servfail(qctx, result)) { 7780 1.1 christos /* 7781 1.1 christos * Don't record this response in the SERVFAIL cache. 7782 1.1 christos */ 7783 1.1 christos qctx->client->attributes |= NS_CLIENTATTR_NOSETFC; 7784 1.1 christos QUERY_ERROR(qctx, DNS_R_SERVFAIL); 7785 1.23 christos return ns_query_done(qctx); 7786 1.1 christos } 7787 1.1 christos 7788 1.1 christos switch (result) { 7789 1.1 christos case ISC_R_SUCCESS: 7790 1.23 christos return query_prepresponse(qctx); 7791 1.1 christos 7792 1.1 christos case DNS_R_GLUE: 7793 1.1 christos case DNS_R_ZONECUT: 7794 1.1 christos INSIST(qctx->is_zone); 7795 1.3 christos qctx->authoritative = false; 7796 1.23 christos return query_prepresponse(qctx); 7797 1.1 christos 7798 1.1 christos case ISC_R_NOTFOUND: 7799 1.23 christos return query_notfound(qctx); 7800 1.1 christos 7801 1.1 christos case DNS_R_DELEGATION: 7802 1.23 christos return query_delegation(qctx); 7803 1.1 christos 7804 1.1 christos case DNS_R_EMPTYNAME: 7805 1.1 christos case DNS_R_NXRRSET: 7806 1.23 christos return query_nodata(qctx, result); 7807 1.1 christos 7808 1.1 christos case DNS_R_EMPTYWILD: 7809 1.1 christos case DNS_R_NXDOMAIN: 7810 1.23 christos return query_nxdomain(qctx, result); 7811 1.1 christos 7812 1.1 christos case DNS_R_COVERINGNSEC: 7813 1.23 christos return query_coveringnsec(qctx); 7814 1.1 christos 7815 1.1 christos case DNS_R_NCACHENXDOMAIN: 7816 1.18 christos result = query_redirect(qctx, result); 7817 1.9 christos if (result != ISC_R_COMPLETE) { 7818 1.23 christos return result; 7819 1.9 christos } 7820 1.23 christos return query_ncache(qctx, DNS_R_NCACHENXDOMAIN); 7821 1.1 christos 7822 1.1 christos case DNS_R_NCACHENXRRSET: 7823 1.23 christos return query_ncache(qctx, DNS_R_NCACHENXRRSET); 7824 1.1 christos 7825 1.1 christos case DNS_R_CNAME: 7826 1.23 christos return query_cname(qctx); 7827 1.1 christos 7828 1.1 christos case DNS_R_DNAME: 7829 1.23 christos return query_dname(qctx); 7830 1.1 christos 7831 1.1 christos default: 7832 1.1 christos /* 7833 1.1 christos * Something has gone wrong. 7834 1.1 christos */ 7835 1.1 christos snprintf(errmsg, sizeof(errmsg) - 1, 7836 1.1 christos "query_gotanswer: unexpected error: %s", 7837 1.1 christos isc_result_totext(result)); 7838 1.1 christos CCTRACE(ISC_LOG_ERROR, errmsg); 7839 1.13 christos if (query_usestale(qctx, result)) { 7840 1.3 christos /* 7841 1.3 christos * If serve-stale is enabled, query_usestale() already 7842 1.3 christos * set up 'qctx' for looking up a stale response. 7843 1.3 christos */ 7844 1.23 christos return query_lookup(qctx); 7845 1.1 christos } 7846 1.6 christos 7847 1.6 christos /* 7848 1.6 christos * Regardless of the triggering result, we definitely 7849 1.6 christos * want to return SERVFAIL from here. 7850 1.6 christos */ 7851 1.6 christos qctx->client->rcode_override = dns_rcode_servfail; 7852 1.6 christos 7853 1.3 christos QUERY_ERROR(qctx, result); 7854 1.23 christos return ns_query_done(qctx); 7855 1.1 christos } 7856 1.3 christos 7857 1.9 christos cleanup: 7858 1.23 christos return result; 7859 1.1 christos } 7860 1.1 christos 7861 1.1 christos static void 7862 1.1 christos query_addnoqnameproof(query_ctx_t *qctx) { 7863 1.1 christos ns_client_t *client = qctx->client; 7864 1.1 christos isc_buffer_t *dbuf, b; 7865 1.1 christos dns_name_t *fname = NULL; 7866 1.1 christos dns_rdataset_t *neg = NULL, *negsig = NULL; 7867 1.1 christos isc_result_t result = ISC_R_NOMEMORY; 7868 1.1 christos 7869 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addnoqnameproof"); 7870 1.1 christos 7871 1.1 christos if (qctx->noqname == NULL) { 7872 1.1 christos return; 7873 1.1 christos } 7874 1.1 christos 7875 1.3 christos dbuf = ns_client_getnamebuf(client); 7876 1.3 christos fname = ns_client_newname(client, dbuf, &b); 7877 1.3 christos neg = ns_client_newrdataset(client); 7878 1.3 christos negsig = ns_client_newrdataset(client); 7879 1.1 christos 7880 1.1 christos result = dns_rdataset_getnoqname(qctx->noqname, fname, neg, negsig); 7881 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 7882 1.1 christos 7883 1.3 christos query_addrrset(qctx, &fname, &neg, &negsig, dbuf, 7884 1.1 christos DNS_SECTION_AUTHORITY); 7885 1.1 christos 7886 1.1 christos if ((qctx->noqname->attributes & DNS_RDATASETATTR_CLOSEST) == 0) { 7887 1.1 christos goto cleanup; 7888 1.1 christos } 7889 1.1 christos 7890 1.1 christos if (fname == NULL) { 7891 1.3 christos dbuf = ns_client_getnamebuf(client); 7892 1.3 christos fname = ns_client_newname(client, dbuf, &b); 7893 1.1 christos } 7894 1.1 christos 7895 1.1 christos if (neg == NULL) { 7896 1.3 christos neg = ns_client_newrdataset(client); 7897 1.1 christos } else if (dns_rdataset_isassociated(neg)) { 7898 1.1 christos dns_rdataset_disassociate(neg); 7899 1.1 christos } 7900 1.1 christos 7901 1.1 christos if (negsig == NULL) { 7902 1.3 christos negsig = ns_client_newrdataset(client); 7903 1.1 christos } else if (dns_rdataset_isassociated(negsig)) { 7904 1.1 christos dns_rdataset_disassociate(negsig); 7905 1.1 christos } 7906 1.1 christos 7907 1.1 christos result = dns_rdataset_getclosest(qctx->noqname, fname, neg, negsig); 7908 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 7909 1.1 christos 7910 1.3 christos query_addrrset(qctx, &fname, &neg, &negsig, dbuf, 7911 1.1 christos DNS_SECTION_AUTHORITY); 7912 1.1 christos 7913 1.9 christos cleanup: 7914 1.1 christos if (neg != NULL) { 7915 1.3 christos ns_client_putrdataset(client, &neg); 7916 1.1 christos } 7917 1.1 christos if (negsig != NULL) { 7918 1.3 christos ns_client_putrdataset(client, &negsig); 7919 1.1 christos } 7920 1.1 christos if (fname != NULL) { 7921 1.3 christos ns_client_releasename(client, &fname); 7922 1.1 christos } 7923 1.1 christos } 7924 1.1 christos 7925 1.1 christos /*% 7926 1.1 christos * Build the response for a query for type ANY. 7927 1.1 christos */ 7928 1.1 christos static isc_result_t 7929 1.1 christos query_respond_any(query_ctx_t *qctx) { 7930 1.5 christos bool found = false, hidden = false; 7931 1.1 christos dns_rdatasetiter_t *rdsiter = NULL; 7932 1.20 christos isc_result_t result = ISC_R_UNSET; 7933 1.9 christos dns_rdatatype_t onetype = 0; /* type to use for minimal-any */ 7934 1.3 christos isc_buffer_t b; 7935 1.1 christos 7936 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_respond_any"); 7937 1.9 christos 7938 1.3 christos CALL_HOOK(NS_QUERY_RESPOND_ANY_BEGIN, qctx); 7939 1.1 christos 7940 1.16 christos result = dns_db_allrdatasets(qctx->db, qctx->node, qctx->version, 0, 0, 7941 1.9 christos &rdsiter); 7942 1.1 christos if (result != ISC_R_SUCCESS) { 7943 1.9 christos CCTRACE(ISC_LOG_ERROR, "query_respond_any: allrdatasets " 7944 1.9 christos "failed"); 7945 1.3 christos QUERY_ERROR(qctx, result); 7946 1.23 christos return ns_query_done(qctx); 7947 1.1 christos } 7948 1.1 christos 7949 1.1 christos /* 7950 1.1 christos * Calling query_addrrset() with a non-NULL dbuf is going 7951 1.1 christos * to either keep or release the name. We don't want it to 7952 1.1 christos * release fname, since we may have to call query_addrrset() 7953 1.3 christos * more than once. That means we have to call ns_client_keepname() 7954 1.1 christos * now, and pass a NULL dbuf to query_addrrset(). 7955 1.1 christos * 7956 1.1 christos * If we do a query_addrrset() below, we must set qctx->fname to 7957 1.1 christos * NULL before leaving this block, otherwise we might try to 7958 1.1 christos * cleanup qctx->fname even though we're using it! 7959 1.1 christos */ 7960 1.3 christos ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); 7961 1.3 christos qctx->tname = qctx->fname; 7962 1.1 christos 7963 1.1 christos result = dns_rdatasetiter_first(rdsiter); 7964 1.1 christos while (result == ISC_R_SUCCESS) { 7965 1.1 christos dns_rdatasetiter_current(rdsiter, qctx->rdataset); 7966 1.1 christos 7967 1.1 christos /* 7968 1.1 christos * We found an NS RRset; no need to add one later. 7969 1.1 christos */ 7970 1.1 christos if (qctx->qtype == dns_rdatatype_any && 7971 1.1 christos qctx->rdataset->type == dns_rdatatype_ns) 7972 1.1 christos { 7973 1.3 christos qctx->answer_has_ns = true; 7974 1.1 christos } 7975 1.1 christos 7976 1.1 christos /* 7977 1.1 christos * Note: if we're in this function, then qctx->type 7978 1.1 christos * is guaranteed to be ANY, but qctx->qtype (i.e. the 7979 1.1 christos * original type requested) might have been RRSIG or 7980 1.1 christos * SIG; we need to check for that. 7981 1.1 christos */ 7982 1.1 christos if (qctx->is_zone && qctx->qtype == dns_rdatatype_any && 7983 1.1 christos !dns_db_issecure(qctx->db) && 7984 1.1 christos dns_rdatatype_isdnssec(qctx->rdataset->type)) 7985 1.1 christos { 7986 1.1 christos /* 7987 1.5 christos * The zone may be transitioning from insecure 7988 1.5 christos * to secure. Hide DNSSEC records from ANY queries. 7989 1.1 christos */ 7990 1.1 christos dns_rdataset_disassociate(qctx->rdataset); 7991 1.5 christos hidden = true; 7992 1.9 christos } else if (qctx->view->minimal_any && !TCP(qctx->client) && 7993 1.9 christos !WANTDNSSEC(qctx->client) && 7994 1.1 christos qctx->qtype == dns_rdatatype_any && 7995 1.1 christos (qctx->rdataset->type == dns_rdatatype_sig || 7996 1.1 christos qctx->rdataset->type == dns_rdatatype_rrsig)) 7997 1.1 christos { 7998 1.1 christos CCTRACE(ISC_LOG_DEBUG(5), "query_respond_any: " 7999 1.9 christos "minimal-any skip signature"); 8000 1.1 christos dns_rdataset_disassociate(qctx->rdataset); 8001 1.9 christos } else if (qctx->view->minimal_any && !TCP(qctx->client) && 8002 1.9 christos onetype != 0 && qctx->rdataset->type != onetype && 8003 1.1 christos qctx->rdataset->covers != onetype) 8004 1.1 christos { 8005 1.1 christos CCTRACE(ISC_LOG_DEBUG(5), "query_respond_any: " 8006 1.9 christos "minimal-any skip rdataset"); 8007 1.1 christos dns_rdataset_disassociate(qctx->rdataset); 8008 1.1 christos } else if ((qctx->qtype == dns_rdatatype_any || 8009 1.1 christos qctx->rdataset->type == qctx->qtype) && 8010 1.1 christos qctx->rdataset->type != 0) 8011 1.1 christos { 8012 1.9 christos if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client)) 8013 1.1 christos { 8014 1.1 christos qctx->noqname = qctx->rdataset; 8015 1.1 christos } else { 8016 1.1 christos qctx->noqname = NULL; 8017 1.1 christos } 8018 1.1 christos 8019 1.1 christos qctx->rpz_st = qctx->client->query.rpz_st; 8020 1.24 christos if (qctx->rpz_st != NULL && 8021 1.24 christos qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS && 8022 1.24 christos qctx->rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU) 8023 1.24 christos { 8024 1.1 christos qctx->rdataset->ttl = 8025 1.1 christos ISC_MIN(qctx->rdataset->ttl, 8026 1.1 christos qctx->rpz_st->m.ttl); 8027 1.9 christos } 8028 1.1 christos 8029 1.1 christos if (!qctx->is_zone && RECURSIONOK(qctx->client)) { 8030 1.1 christos dns_name_t *name; 8031 1.9 christos name = (qctx->fname != NULL) ? qctx->fname 8032 1.9 christos : qctx->tname; 8033 1.1 christos query_prefetch(qctx->client, name, 8034 1.1 christos qctx->rdataset); 8035 1.1 christos } 8036 1.1 christos 8037 1.1 christos /* 8038 1.1 christos * Remember the first RRtype we find so we 8039 1.1 christos * can skip others with minimal-any. 8040 1.1 christos */ 8041 1.1 christos if (qctx->rdataset->type == dns_rdatatype_sig || 8042 1.1 christos qctx->rdataset->type == dns_rdatatype_rrsig) 8043 1.3 christos { 8044 1.1 christos onetype = qctx->rdataset->covers; 8045 1.3 christos } else { 8046 1.1 christos onetype = qctx->rdataset->type; 8047 1.3 christos } 8048 1.1 christos 8049 1.3 christos query_addrrset(qctx, 8050 1.9 christos (qctx->fname != NULL) ? &qctx->fname 8051 1.9 christos : &qctx->tname, 8052 1.9 christos &qctx->rdataset, NULL, NULL, 8053 1.9 christos DNS_SECTION_ANSWER); 8054 1.1 christos 8055 1.1 christos query_addnoqnameproof(qctx); 8056 1.1 christos 8057 1.3 christos found = true; 8058 1.3 christos INSIST(qctx->tname != NULL); 8059 1.1 christos 8060 1.1 christos /* 8061 1.1 christos * rdataset is non-NULL only in certain 8062 1.1 christos * pathological cases involving DNAMEs. 8063 1.1 christos */ 8064 1.3 christos if (qctx->rdataset != NULL) { 8065 1.3 christos ns_client_putrdataset(qctx->client, 8066 1.3 christos &qctx->rdataset); 8067 1.3 christos } 8068 1.1 christos 8069 1.3 christos qctx->rdataset = ns_client_newrdataset(qctx->client); 8070 1.1 christos } else { 8071 1.1 christos /* 8072 1.1 christos * We're not interested in this rdataset. 8073 1.1 christos */ 8074 1.1 christos dns_rdataset_disassociate(qctx->rdataset); 8075 1.1 christos } 8076 1.1 christos 8077 1.1 christos result = dns_rdatasetiter_next(rdsiter); 8078 1.1 christos } 8079 1.1 christos 8080 1.3 christos dns_rdatasetiter_destroy(&rdsiter); 8081 1.3 christos 8082 1.3 christos if (result != ISC_R_NOMORE) { 8083 1.9 christos CCTRACE(ISC_LOG_ERROR, "query_respond_any: rdataset iterator " 8084 1.9 christos "failed"); 8085 1.3 christos QUERY_ERROR(qctx, DNS_R_SERVFAIL); 8086 1.23 christos return ns_query_done(qctx); 8087 1.3 christos } 8088 1.3 christos 8089 1.3 christos if (found) { 8090 1.5 christos /* 8091 1.5 christos * Call hook if any answers were found. 8092 1.5 christos * Do this before releasing qctx->fname, in case 8093 1.5 christos * the hook function needs it. 8094 1.5 christos */ 8095 1.3 christos CALL_HOOK(NS_QUERY_RESPOND_ANY_FOUND, qctx); 8096 1.3 christos } 8097 1.3 christos 8098 1.3 christos if (qctx->fname != NULL) { 8099 1.5 christos dns_message_puttempname(qctx->client->message, &qctx->fname); 8100 1.1 christos } 8101 1.1 christos 8102 1.5 christos if (found) { 8103 1.5 christos /* 8104 1.5 christos * At least one matching rdataset was found 8105 1.5 christos */ 8106 1.1 christos query_addauth(qctx); 8107 1.5 christos } else if (qctx->qtype == dns_rdatatype_rrsig || 8108 1.5 christos qctx->qtype == dns_rdatatype_sig) 8109 1.5 christos { 8110 1.5 christos /* 8111 1.5 christos * No matching rdatasets were found, but we got 8112 1.5 christos * here on a search for RRSIG/SIG, so that's okay. 8113 1.5 christos */ 8114 1.5 christos if (!qctx->is_zone) { 8115 1.5 christos qctx->authoritative = false; 8116 1.5 christos qctx->client->attributes &= ~NS_CLIENTATTR_RA; 8117 1.5 christos query_addauth(qctx); 8118 1.23 christos return ns_query_done(qctx); 8119 1.5 christos } 8120 1.5 christos 8121 1.5 christos if (qctx->qtype == dns_rdatatype_rrsig && 8122 1.16 christos dns_db_issecure(qctx->db)) 8123 1.16 christos { 8124 1.5 christos char namebuf[DNS_NAME_FORMATSIZE]; 8125 1.9 christos dns_name_format(qctx->client->query.qname, namebuf, 8126 1.9 christos sizeof(namebuf)); 8127 1.5 christos ns_client_log(qctx->client, DNS_LOGCATEGORY_DNSSEC, 8128 1.5 christos NS_LOGMODULE_QUERY, ISC_LOG_WARNING, 8129 1.5 christos "missing signature for %s", namebuf); 8130 1.5 christos } 8131 1.1 christos 8132 1.5 christos qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b); 8133 1.23 christos return query_sign_nodata(qctx); 8134 1.5 christos } else if (!hidden) { 8135 1.5 christos /* 8136 1.5 christos * No matching rdatasets were found and nothing was 8137 1.5 christos * deliberately hidden: something must have gone wrong. 8138 1.5 christos */ 8139 1.5 christos QUERY_ERROR(qctx, DNS_R_SERVFAIL); 8140 1.3 christos } 8141 1.3 christos 8142 1.23 christos return ns_query_done(qctx); 8143 1.3 christos 8144 1.9 christos cleanup: 8145 1.23 christos return result; 8146 1.1 christos } 8147 1.1 christos 8148 1.1 christos /* 8149 1.20 christos * Set the expire time, if requested, when answering from a secondary, 8150 1.20 christos * mirror, or primary zone. 8151 1.1 christos */ 8152 1.1 christos static void 8153 1.1 christos query_getexpire(query_ctx_t *qctx) { 8154 1.1 christos dns_zone_t *raw = NULL, *mayberaw; 8155 1.1 christos 8156 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_getexpire"); 8157 1.9 christos 8158 1.1 christos if (qctx->zone == NULL || !qctx->is_zone || 8159 1.1 christos qctx->qtype != dns_rdatatype_soa || 8160 1.1 christos qctx->client->query.restarts != 0 || 8161 1.1 christos (qctx->client->attributes & NS_CLIENTATTR_WANTEXPIRE) == 0) 8162 1.1 christos { 8163 1.1 christos return; 8164 1.1 christos } 8165 1.1 christos 8166 1.1 christos dns_zone_getraw(qctx->zone, &raw); 8167 1.1 christos mayberaw = (raw != NULL) ? raw : qctx->zone; 8168 1.1 christos 8169 1.15 christos if (dns_zone_gettype(mayberaw) == dns_zone_secondary || 8170 1.3 christos dns_zone_gettype(mayberaw) == dns_zone_mirror) 8171 1.3 christos { 8172 1.1 christos isc_time_t expiretime; 8173 1.3 christos uint32_t secs; 8174 1.1 christos dns_zone_getexpiretime(qctx->zone, &expiretime); 8175 1.1 christos secs = isc_time_seconds(&expiretime); 8176 1.9 christos if (secs >= qctx->client->now && qctx->result == ISC_R_SUCCESS) 8177 1.1 christos { 8178 1.9 christos qctx->client->attributes |= NS_CLIENTATTR_HAVEEXPIRE; 8179 1.1 christos qctx->client->expire = secs - qctx->client->now; 8180 1.1 christos } 8181 1.15 christos } else if (dns_zone_gettype(mayberaw) == dns_zone_primary) { 8182 1.1 christos isc_result_t result; 8183 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 8184 1.1 christos dns_rdata_soa_t soa; 8185 1.1 christos 8186 1.1 christos result = dns_rdataset_first(qctx->rdataset); 8187 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 8188 1.1 christos 8189 1.1 christos dns_rdataset_current(qctx->rdataset, &rdata); 8190 1.1 christos result = dns_rdata_tostruct(&rdata, &soa, NULL); 8191 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 8192 1.1 christos 8193 1.1 christos qctx->client->expire = soa.expire; 8194 1.1 christos qctx->client->attributes |= NS_CLIENTATTR_HAVEEXPIRE; 8195 1.1 christos } 8196 1.1 christos 8197 1.1 christos if (raw != NULL) { 8198 1.1 christos dns_zone_detach(&raw); 8199 1.1 christos } 8200 1.1 christos } 8201 1.1 christos 8202 1.3 christos /*% 8203 1.3 christos * Fill the ANSWER section of a positive response. 8204 1.1 christos */ 8205 1.1 christos static isc_result_t 8206 1.3 christos query_addanswer(query_ctx_t *qctx) { 8207 1.3 christos dns_rdataset_t **sigrdatasetp = NULL; 8208 1.20 christos isc_result_t result = ISC_R_UNSET; 8209 1.1 christos 8210 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_addanswer"); 8211 1.9 christos 8212 1.3 christos CALL_HOOK(NS_QUERY_ADDANSWER_BEGIN, qctx); 8213 1.1 christos 8214 1.3 christos if (qctx->dns64) { 8215 1.3 christos result = query_dns64(qctx); 8216 1.3 christos qctx->noqname = NULL; 8217 1.3 christos dns_rdataset_disassociate(qctx->rdataset); 8218 1.3 christos dns_message_puttemprdataset(qctx->client->message, 8219 1.3 christos &qctx->rdataset); 8220 1.3 christos if (result == ISC_R_NOMORE) { 8221 1.3 christos #ifndef dns64_bis_return_excluded_addresses 8222 1.3 christos if (qctx->dns64_exclude) { 8223 1.9 christos if (!qctx->is_zone) { 8224 1.23 christos return ns_query_done(qctx); 8225 1.9 christos } 8226 1.3 christos /* 8227 1.3 christos * Add a fake SOA record. 8228 1.3 christos */ 8229 1.3 christos (void)query_addsoa(qctx, 600, 8230 1.3 christos DNS_SECTION_AUTHORITY); 8231 1.23 christos return ns_query_done(qctx); 8232 1.3 christos } 8233 1.9 christos #endif /* ifndef dns64_bis_return_excluded_addresses */ 8234 1.3 christos if (qctx->is_zone) { 8235 1.23 christos return query_nodata(qctx, DNS_R_NXDOMAIN); 8236 1.3 christos } else { 8237 1.23 christos return query_ncache(qctx, DNS_R_NXDOMAIN); 8238 1.1 christos } 8239 1.3 christos } else if (result != ISC_R_SUCCESS) { 8240 1.3 christos qctx->result = result; 8241 1.23 christos return ns_query_done(qctx); 8242 1.3 christos } 8243 1.3 christos } else if (qctx->client->query.dns64_aaaaok != NULL) { 8244 1.3 christos query_filter64(qctx); 8245 1.3 christos ns_client_putrdataset(qctx->client, &qctx->rdataset); 8246 1.3 christos } else { 8247 1.26 christos if (!qctx->is_zone && RECURSIONOK(qctx->client)) { 8248 1.3 christos query_prefetch(qctx->client, qctx->fname, 8249 1.3 christos qctx->rdataset); 8250 1.1 christos } 8251 1.3 christos if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) { 8252 1.3 christos sigrdatasetp = &qctx->sigrdataset; 8253 1.3 christos } 8254 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, 8255 1.9 christos sigrdatasetp, qctx->dbuf, DNS_SECTION_ANSWER); 8256 1.1 christos } 8257 1.1 christos 8258 1.23 christos return ISC_R_COMPLETE; 8259 1.3 christos 8260 1.9 christos cleanup: 8261 1.23 christos return result; 8262 1.1 christos } 8263 1.1 christos 8264 1.1 christos /*% 8265 1.9 christos * Build a response for a "normal" query, for a type other than ANY, 8266 1.1 christos * for which we have an answer (either positive or negative). 8267 1.1 christos */ 8268 1.1 christos static isc_result_t 8269 1.1 christos query_respond(query_ctx_t *qctx) { 8270 1.20 christos isc_result_t result = ISC_R_UNSET; 8271 1.1 christos 8272 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_respond"); 8273 1.9 christos 8274 1.1 christos /* 8275 1.1 christos * Check to see if the AAAA RRset has non-excluded addresses 8276 1.1 christos * in it. If not look for a A RRset. 8277 1.1 christos */ 8278 1.1 christos INSIST(qctx->client->query.dns64_aaaaok == NULL); 8279 1.1 christos 8280 1.1 christos if (qctx->qtype == dns_rdatatype_aaaa && !qctx->dns64_exclude && 8281 1.3 christos !ISC_LIST_EMPTY(qctx->view->dns64) && 8282 1.1 christos qctx->client->message->rdclass == dns_rdataclass_in && 8283 1.1 christos !dns64_aaaaok(qctx->client, qctx->rdataset, qctx->sigrdataset)) 8284 1.1 christos { 8285 1.1 christos /* 8286 1.1 christos * Look to see if there are A records for this name. 8287 1.1 christos */ 8288 1.1 christos qctx->client->query.dns64_ttl = qctx->rdataset->ttl; 8289 1.1 christos SAVE(qctx->client->query.dns64_aaaa, qctx->rdataset); 8290 1.1 christos SAVE(qctx->client->query.dns64_sigaaaa, qctx->sigrdataset); 8291 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 8292 1.1 christos dns_db_detachnode(qctx->db, &qctx->node); 8293 1.1 christos qctx->type = qctx->qtype = dns_rdatatype_a; 8294 1.3 christos qctx->dns64_exclude = qctx->dns64 = true; 8295 1.1 christos 8296 1.23 christos return query_lookup(qctx); 8297 1.1 christos } 8298 1.1 christos 8299 1.3 christos /* 8300 1.3 christos * XXX: This hook is meant to be at the top of this function, 8301 1.3 christos * but is postponed until after DNS64 in order to avoid an 8302 1.3 christos * assertion if the hook causes recursion. (When DNS64 also 8303 1.3 christos * becomes a plugin, it will be necessary to find some 8304 1.3 christos * other way to prevent that assertion, since the order in 8305 1.3 christos * which plugins are configured can't be enforced.) 8306 1.3 christos */ 8307 1.3 christos CALL_HOOK(NS_QUERY_RESPOND_BEGIN, qctx); 8308 1.1 christos 8309 1.1 christos if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client)) { 8310 1.1 christos qctx->noqname = qctx->rdataset; 8311 1.1 christos } else { 8312 1.1 christos qctx->noqname = NULL; 8313 1.1 christos } 8314 1.1 christos 8315 1.1 christos /* 8316 1.1 christos * Special case NS handling 8317 1.1 christos */ 8318 1.1 christos if (qctx->is_zone && qctx->qtype == dns_rdatatype_ns) { 8319 1.1 christos /* 8320 1.1 christos * We've already got an NS, no need to add one in 8321 1.1 christos * the authority section 8322 1.1 christos */ 8323 1.1 christos if (dns_name_equal(qctx->client->query.qname, 8324 1.16 christos dns_db_origin(qctx->db))) 8325 1.16 christos { 8326 1.3 christos qctx->answer_has_ns = true; 8327 1.1 christos } 8328 1.1 christos 8329 1.1 christos /* 8330 1.6 christos * Always add glue for root priming queries, regardless 8331 1.6 christos * of "minimal-responses" setting. 8332 1.1 christos */ 8333 1.1 christos if (dns_name_equal(qctx->client->query.qname, dns_rootname)) { 8334 1.1 christos qctx->client->query.attributes &= 8335 1.1 christos ~NS_QUERYATTR_NOADDITIONAL; 8336 1.6 christos dns_db_attach(qctx->db, &qctx->client->query.gluedb); 8337 1.1 christos } 8338 1.1 christos } 8339 1.1 christos 8340 1.1 christos /* 8341 1.1 christos * Set expire time 8342 1.1 christos */ 8343 1.1 christos query_getexpire(qctx); 8344 1.1 christos 8345 1.3 christos result = query_addanswer(qctx); 8346 1.3 christos if (result != ISC_R_COMPLETE) { 8347 1.23 christos return result; 8348 1.1 christos } 8349 1.1 christos 8350 1.1 christos query_addnoqnameproof(qctx); 8351 1.1 christos 8352 1.1 christos /* 8353 1.13 christos * 'qctx->rdataset' will only be non-NULL here if the ANSWER section of 8354 1.13 christos * the message to be sent to the client already contains an RRset with 8355 1.13 christos * the same owner name and the same type as 'qctx->rdataset'. This 8356 1.13 christos * should never happen, with one exception: when chasing DNAME records, 8357 1.13 christos * one of the DNAME records placed in the ANSWER section may turn out 8358 1.13 christos * to be the final answer to the client's query, but we have no way of 8359 1.13 christos * knowing that until now. In such a case, 'qctx->rdataset' will be 8360 1.13 christos * freed later, so we do not need to free it here. 8361 1.1 christos */ 8362 1.13 christos INSIST(qctx->rdataset == NULL || qctx->qtype == dns_rdatatype_dname); 8363 1.1 christos 8364 1.1 christos query_addauth(qctx); 8365 1.1 christos 8366 1.23 christos return ns_query_done(qctx); 8367 1.3 christos 8368 1.9 christos cleanup: 8369 1.23 christos return result; 8370 1.1 christos } 8371 1.1 christos 8372 1.1 christos static isc_result_t 8373 1.1 christos query_dns64(query_ctx_t *qctx) { 8374 1.1 christos ns_client_t *client = qctx->client; 8375 1.20 christos dns_aclenv_t *env = client->manager->aclenv; 8376 1.1 christos dns_name_t *name, *mname; 8377 1.1 christos dns_rdata_t *dns64_rdata; 8378 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 8379 1.1 christos dns_rdatalist_t *dns64_rdatalist; 8380 1.1 christos dns_rdataset_t *dns64_rdataset; 8381 1.1 christos dns_rdataset_t *mrdataset; 8382 1.1 christos isc_buffer_t *buffer; 8383 1.1 christos isc_region_t r; 8384 1.1 christos isc_result_t result; 8385 1.1 christos dns_view_t *view = client->view; 8386 1.1 christos isc_netaddr_t netaddr; 8387 1.1 christos dns_dns64_t *dns64; 8388 1.1 christos unsigned int flags = 0; 8389 1.1 christos const dns_section_t section = DNS_SECTION_ANSWER; 8390 1.1 christos 8391 1.1 christos /*% 8392 1.1 christos * To the current response for 'qctx->client', add the answer RRset 8393 1.1 christos * '*rdatasetp' and an optional signature set '*sigrdatasetp', with 8394 1.1 christos * owner name '*namep', to the answer section, unless they are 8395 1.1 christos * already there. Also add any pertinent additional data. 8396 1.1 christos * 8397 1.1 christos * If 'qctx->dbuf' is not NULL, then 'qctx->fname' is the name 8398 1.1 christos * whose data is stored 'qctx->dbuf'. In this case, 8399 1.1 christos * query_addrrset() guarantees that when it returns the name 8400 1.1 christos * will either have been kept or released. 8401 1.1 christos */ 8402 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_dns64"); 8403 1.1 christos 8404 1.1 christos qctx->qtype = qctx->type = dns_rdatatype_aaaa; 8405 1.1 christos 8406 1.1 christos name = qctx->fname; 8407 1.1 christos mname = NULL; 8408 1.1 christos mrdataset = NULL; 8409 1.1 christos buffer = NULL; 8410 1.1 christos dns64_rdata = NULL; 8411 1.1 christos dns64_rdataset = NULL; 8412 1.1 christos dns64_rdatalist = NULL; 8413 1.9 christos result = dns_message_findname( 8414 1.9 christos client->message, section, name, dns_rdatatype_aaaa, 8415 1.9 christos qctx->rdataset->covers, &mname, &mrdataset); 8416 1.1 christos if (result == ISC_R_SUCCESS) { 8417 1.1 christos /* 8418 1.1 christos * We've already got an RRset of the given name and type. 8419 1.1 christos * There's nothing else to do; 8420 1.1 christos */ 8421 1.9 christos CTRACE(ISC_LOG_DEBUG(3), "query_dns64: dns_message_findname " 8422 1.9 christos "succeeded: done"); 8423 1.3 christos if (qctx->dbuf != NULL) { 8424 1.3 christos ns_client_releasename(client, &qctx->fname); 8425 1.3 christos } 8426 1.23 christos return ISC_R_SUCCESS; 8427 1.1 christos } else if (result == DNS_R_NXDOMAIN) { 8428 1.1 christos /* 8429 1.1 christos * The name doesn't exist. 8430 1.1 christos */ 8431 1.3 christos if (qctx->dbuf != NULL) { 8432 1.3 christos ns_client_keepname(client, name, qctx->dbuf); 8433 1.3 christos } 8434 1.1 christos dns_message_addname(client->message, name, section); 8435 1.1 christos qctx->fname = NULL; 8436 1.1 christos mname = name; 8437 1.1 christos } else { 8438 1.1 christos RUNTIME_CHECK(result == DNS_R_NXRRSET); 8439 1.3 christos if (qctx->dbuf != NULL) { 8440 1.3 christos ns_client_releasename(client, &qctx->fname); 8441 1.3 christos } 8442 1.1 christos } 8443 1.1 christos 8444 1.1 christos if (qctx->rdataset->trust != dns_trust_secure) { 8445 1.1 christos client->query.attributes &= ~NS_QUERYATTR_SECURE; 8446 1.1 christos } 8447 1.1 christos 8448 1.1 christos isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); 8449 1.1 christos 8450 1.23 christos isc_buffer_allocate(client->manager->mctx, &buffer, 8451 1.9 christos view->dns64cnt * 16 * 8452 1.9 christos dns_rdataset_count(qctx->rdataset)); 8453 1.23 christos dns_message_gettemprdataset(client->message, &dns64_rdataset); 8454 1.23 christos dns_message_gettemprdatalist(client->message, &dns64_rdatalist); 8455 1.1 christos 8456 1.1 christos dns_rdatalist_init(dns64_rdatalist); 8457 1.1 christos dns64_rdatalist->rdclass = dns_rdataclass_in; 8458 1.1 christos dns64_rdatalist->type = dns_rdatatype_aaaa; 8459 1.9 christos if (client->query.dns64_ttl != UINT32_MAX) { 8460 1.1 christos dns64_rdatalist->ttl = ISC_MIN(qctx->rdataset->ttl, 8461 1.1 christos client->query.dns64_ttl); 8462 1.9 christos } else { 8463 1.1 christos dns64_rdatalist->ttl = ISC_MIN(qctx->rdataset->ttl, 600); 8464 1.9 christos } 8465 1.1 christos 8466 1.9 christos if (RECURSIONOK(client)) { 8467 1.1 christos flags |= DNS_DNS64_RECURSIVE; 8468 1.9 christos } 8469 1.1 christos 8470 1.1 christos /* 8471 1.1 christos * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC 8472 1.1 christos * as this provides a easy way to see if the answer was signed. 8473 1.1 christos */ 8474 1.1 christos if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL && 8475 1.1 christos dns_rdataset_isassociated(qctx->sigrdataset)) 8476 1.9 christos { 8477 1.1 christos flags |= DNS_DNS64_DNSSEC; 8478 1.9 christos } 8479 1.1 christos 8480 1.1 christos for (result = dns_rdataset_first(qctx->rdataset); 8481 1.1 christos result == ISC_R_SUCCESS; 8482 1.9 christos result = dns_rdataset_next(qctx->rdataset)) 8483 1.9 christos { 8484 1.9 christos for (dns64 = ISC_LIST_HEAD(client->view->dns64); dns64 != NULL; 8485 1.9 christos dns64 = dns_dns64_next(dns64)) 8486 1.9 christos { 8487 1.1 christos dns_rdataset_current(qctx->rdataset, &rdata); 8488 1.1 christos isc_buffer_availableregion(buffer, &r); 8489 1.1 christos INSIST(r.length >= 16); 8490 1.1 christos result = dns_dns64_aaaafroma(dns64, &netaddr, 8491 1.1 christos client->signer, env, flags, 8492 1.1 christos rdata.data, r.base); 8493 1.1 christos if (result != ISC_R_SUCCESS) { 8494 1.1 christos dns_rdata_reset(&rdata); 8495 1.1 christos continue; 8496 1.1 christos } 8497 1.1 christos isc_buffer_add(buffer, 16); 8498 1.1 christos isc_buffer_remainingregion(buffer, &r); 8499 1.1 christos isc_buffer_forward(buffer, 16); 8500 1.23 christos dns_message_gettemprdata(client->message, &dns64_rdata); 8501 1.1 christos dns_rdata_init(dns64_rdata); 8502 1.1 christos dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in, 8503 1.1 christos dns_rdatatype_aaaa, &r); 8504 1.1 christos ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata, 8505 1.1 christos link); 8506 1.1 christos dns64_rdata = NULL; 8507 1.1 christos dns_rdata_reset(&rdata); 8508 1.1 christos } 8509 1.1 christos } 8510 1.9 christos if (result != ISC_R_NOMORE) { 8511 1.1 christos goto cleanup; 8512 1.9 christos } 8513 1.1 christos 8514 1.9 christos if (ISC_LIST_EMPTY(dns64_rdatalist->rdata)) { 8515 1.1 christos goto cleanup; 8516 1.9 christos } 8517 1.1 christos 8518 1.23 christos dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset); 8519 1.1 christos dns_rdataset_setownercase(dns64_rdataset, mname); 8520 1.1 christos client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; 8521 1.1 christos dns64_rdataset->trust = qctx->rdataset->trust; 8522 1.3 christos 8523 1.3 christos query_addtoname(mname, dns64_rdataset); 8524 1.3 christos query_setorder(qctx, mname, dns64_rdataset); 8525 1.3 christos 8526 1.1 christos dns64_rdataset = NULL; 8527 1.1 christos dns64_rdatalist = NULL; 8528 1.1 christos dns_message_takebuffer(client->message, &buffer); 8529 1.1 christos inc_stats(client, ns_statscounter_dns64); 8530 1.1 christos result = ISC_R_SUCCESS; 8531 1.1 christos 8532 1.9 christos cleanup: 8533 1.9 christos if (buffer != NULL) { 8534 1.1 christos isc_buffer_free(&buffer); 8535 1.9 christos } 8536 1.1 christos 8537 1.9 christos if (dns64_rdataset != NULL) { 8538 1.1 christos dns_message_puttemprdataset(client->message, &dns64_rdataset); 8539 1.9 christos } 8540 1.1 christos 8541 1.1 christos if (dns64_rdatalist != NULL) { 8542 1.1 christos for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata); 8543 1.1 christos dns64_rdata != NULL; 8544 1.1 christos dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata)) 8545 1.1 christos { 8546 1.9 christos ISC_LIST_UNLINK(dns64_rdatalist->rdata, dns64_rdata, 8547 1.9 christos link); 8548 1.1 christos dns_message_puttemprdata(client->message, &dns64_rdata); 8549 1.1 christos } 8550 1.1 christos dns_message_puttemprdatalist(client->message, &dns64_rdatalist); 8551 1.1 christos } 8552 1.1 christos 8553 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_dns64: done"); 8554 1.23 christos return result; 8555 1.1 christos } 8556 1.1 christos 8557 1.1 christos static void 8558 1.1 christos query_filter64(query_ctx_t *qctx) { 8559 1.1 christos ns_client_t *client = qctx->client; 8560 1.1 christos dns_name_t *name, *mname; 8561 1.1 christos dns_rdata_t *myrdata; 8562 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 8563 1.1 christos dns_rdatalist_t *myrdatalist; 8564 1.1 christos dns_rdataset_t *myrdataset; 8565 1.1 christos isc_buffer_t *buffer; 8566 1.1 christos isc_region_t r; 8567 1.1 christos isc_result_t result; 8568 1.1 christos unsigned int i; 8569 1.1 christos const dns_section_t section = DNS_SECTION_ANSWER; 8570 1.1 christos 8571 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_filter64"); 8572 1.1 christos 8573 1.1 christos INSIST(client->query.dns64_aaaaok != NULL); 8574 1.1 christos INSIST(client->query.dns64_aaaaoklen == 8575 1.1 christos dns_rdataset_count(qctx->rdataset)); 8576 1.1 christos 8577 1.1 christos name = qctx->fname; 8578 1.1 christos mname = NULL; 8579 1.1 christos buffer = NULL; 8580 1.1 christos myrdata = NULL; 8581 1.1 christos myrdataset = NULL; 8582 1.1 christos myrdatalist = NULL; 8583 1.9 christos result = dns_message_findname( 8584 1.9 christos client->message, section, name, dns_rdatatype_aaaa, 8585 1.9 christos qctx->rdataset->covers, &mname, &myrdataset); 8586 1.1 christos if (result == ISC_R_SUCCESS) { 8587 1.1 christos /* 8588 1.1 christos * We've already got an RRset of the given name and type. 8589 1.1 christos * There's nothing else to do; 8590 1.1 christos */ 8591 1.9 christos CTRACE(ISC_LOG_DEBUG(3), "query_filter64: dns_message_findname " 8592 1.9 christos "succeeded: done"); 8593 1.3 christos if (qctx->dbuf != NULL) { 8594 1.3 christos ns_client_releasename(client, &qctx->fname); 8595 1.3 christos } 8596 1.1 christos return; 8597 1.1 christos } else if (result == DNS_R_NXDOMAIN) { 8598 1.1 christos mname = name; 8599 1.1 christos qctx->fname = NULL; 8600 1.1 christos } else { 8601 1.1 christos RUNTIME_CHECK(result == DNS_R_NXRRSET); 8602 1.3 christos if (qctx->dbuf != NULL) { 8603 1.3 christos ns_client_releasename(client, &qctx->fname); 8604 1.3 christos } 8605 1.1 christos qctx->dbuf = NULL; 8606 1.1 christos } 8607 1.1 christos 8608 1.1 christos if (qctx->rdataset->trust != dns_trust_secure) { 8609 1.1 christos client->query.attributes &= ~NS_QUERYATTR_SECURE; 8610 1.1 christos } 8611 1.1 christos 8612 1.23 christos isc_buffer_allocate(client->manager->mctx, &buffer, 8613 1.9 christos 16 * dns_rdataset_count(qctx->rdataset)); 8614 1.23 christos dns_message_gettemprdataset(client->message, &myrdataset); 8615 1.23 christos dns_message_gettemprdatalist(client->message, &myrdatalist); 8616 1.1 christos 8617 1.1 christos dns_rdatalist_init(myrdatalist); 8618 1.1 christos myrdatalist->rdclass = dns_rdataclass_in; 8619 1.1 christos myrdatalist->type = dns_rdatatype_aaaa; 8620 1.1 christos myrdatalist->ttl = qctx->rdataset->ttl; 8621 1.1 christos 8622 1.1 christos i = 0; 8623 1.1 christos for (result = dns_rdataset_first(qctx->rdataset); 8624 1.1 christos result == ISC_R_SUCCESS; 8625 1.3 christos result = dns_rdataset_next(qctx->rdataset)) 8626 1.3 christos { 8627 1.9 christos if (!client->query.dns64_aaaaok[i++]) { 8628 1.1 christos continue; 8629 1.9 christos } 8630 1.1 christos dns_rdataset_current(qctx->rdataset, &rdata); 8631 1.1 christos INSIST(rdata.length == 16); 8632 1.1 christos isc_buffer_putmem(buffer, rdata.data, rdata.length); 8633 1.1 christos isc_buffer_remainingregion(buffer, &r); 8634 1.1 christos isc_buffer_forward(buffer, rdata.length); 8635 1.23 christos dns_message_gettemprdata(client->message, &myrdata); 8636 1.1 christos dns_rdata_init(myrdata); 8637 1.1 christos dns_rdata_fromregion(myrdata, dns_rdataclass_in, 8638 1.1 christos dns_rdatatype_aaaa, &r); 8639 1.1 christos ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link); 8640 1.1 christos myrdata = NULL; 8641 1.1 christos dns_rdata_reset(&rdata); 8642 1.1 christos } 8643 1.9 christos if (result != ISC_R_NOMORE) { 8644 1.1 christos goto cleanup; 8645 1.9 christos } 8646 1.1 christos 8647 1.23 christos dns_rdatalist_tordataset(myrdatalist, myrdataset); 8648 1.1 christos dns_rdataset_setownercase(myrdataset, name); 8649 1.1 christos client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; 8650 1.1 christos if (mname == name) { 8651 1.3 christos if (qctx->dbuf != NULL) { 8652 1.3 christos ns_client_keepname(client, name, qctx->dbuf); 8653 1.3 christos } 8654 1.9 christos dns_message_addname(client->message, name, section); 8655 1.1 christos qctx->dbuf = NULL; 8656 1.1 christos } 8657 1.1 christos myrdataset->trust = qctx->rdataset->trust; 8658 1.3 christos 8659 1.3 christos query_addtoname(mname, myrdataset); 8660 1.3 christos query_setorder(qctx, mname, myrdataset); 8661 1.3 christos 8662 1.1 christos myrdataset = NULL; 8663 1.1 christos myrdatalist = NULL; 8664 1.1 christos dns_message_takebuffer(client->message, &buffer); 8665 1.1 christos 8666 1.9 christos cleanup: 8667 1.9 christos if (buffer != NULL) { 8668 1.1 christos isc_buffer_free(&buffer); 8669 1.9 christos } 8670 1.1 christos 8671 1.9 christos if (myrdataset != NULL) { 8672 1.1 christos dns_message_puttemprdataset(client->message, &myrdataset); 8673 1.9 christos } 8674 1.1 christos 8675 1.1 christos if (myrdatalist != NULL) { 8676 1.1 christos for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata); 8677 1.1 christos myrdata != NULL; 8678 1.1 christos myrdata = ISC_LIST_HEAD(myrdatalist->rdata)) 8679 1.1 christos { 8680 1.1 christos ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link); 8681 1.1 christos dns_message_puttemprdata(client->message, &myrdata); 8682 1.1 christos } 8683 1.1 christos dns_message_puttemprdatalist(client->message, &myrdatalist); 8684 1.1 christos } 8685 1.23 christos 8686 1.3 christos if (qctx->dbuf != NULL) { 8687 1.3 christos ns_client_releasename(client, &name); 8688 1.3 christos } 8689 1.1 christos 8690 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_filter64: done"); 8691 1.1 christos } 8692 1.1 christos 8693 1.1 christos /*% 8694 1.1 christos * Handle the case of a name not being found in a database lookup. 8695 1.1 christos * Called from query_gotanswer(). Passes off processing to 8696 1.1 christos * query_delegation() for a root referral if appropriate. 8697 1.1 christos */ 8698 1.1 christos static isc_result_t 8699 1.1 christos query_notfound(query_ctx_t *qctx) { 8700 1.20 christos isc_result_t result = ISC_R_UNSET; 8701 1.1 christos 8702 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_notfound"); 8703 1.9 christos 8704 1.3 christos CALL_HOOK(NS_QUERY_NOTFOUND_BEGIN, qctx); 8705 1.3 christos 8706 1.1 christos INSIST(!qctx->is_zone); 8707 1.1 christos 8708 1.9 christos if (qctx->db != NULL) { 8709 1.1 christos dns_db_detach(&qctx->db); 8710 1.9 christos } 8711 1.1 christos 8712 1.1 christos /* 8713 1.1 christos * If the cache doesn't even have the root NS, 8714 1.1 christos * try to get that from the hints DB. 8715 1.1 christos */ 8716 1.3 christos if (qctx->view->hints != NULL) { 8717 1.1 christos dns_clientinfomethods_t cm; 8718 1.1 christos dns_clientinfo_t ci; 8719 1.1 christos 8720 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 8721 1.20 christos dns_clientinfo_init(&ci, qctx->client, NULL); 8722 1.1 christos 8723 1.3 christos dns_db_attach(qctx->view->hints, &qctx->db); 8724 1.9 christos result = dns_db_findext(qctx->db, dns_rootname, NULL, 8725 1.9 christos dns_rdatatype_ns, 0, qctx->client->now, 8726 1.9 christos &qctx->node, qctx->fname, &cm, &ci, 8727 1.1 christos qctx->rdataset, qctx->sigrdataset); 8728 1.1 christos } else { 8729 1.1 christos /* We have no hints. */ 8730 1.1 christos result = ISC_R_FAILURE; 8731 1.1 christos } 8732 1.1 christos if (result != ISC_R_SUCCESS) { 8733 1.1 christos /* 8734 1.1 christos * Nonsensical root hints may require cleanup. 8735 1.1 christos */ 8736 1.1 christos qctx_clean(qctx); 8737 1.1 christos 8738 1.1 christos /* 8739 1.1 christos * We don't have any root server hints, but 8740 1.1 christos * we may have working forwarders, so try to 8741 1.1 christos * recurse anyway. 8742 1.1 christos */ 8743 1.1 christos if (RECURSIONOK(qctx->client)) { 8744 1.1 christos INSIST(!REDIRECT(qctx->client)); 8745 1.3 christos result = ns_query_recurse(qctx->client, qctx->qtype, 8746 1.3 christos qctx->client->query.qname, 8747 1.3 christos NULL, NULL, qctx->resuming); 8748 1.1 christos if (result == ISC_R_SUCCESS) { 8749 1.3 christos CALL_HOOK(NS_QUERY_NOTFOUND_RECURSE, qctx); 8750 1.1 christos qctx->client->query.attributes |= 8751 1.9 christos NS_QUERYATTR_RECURSING; 8752 1.3 christos 8753 1.3 christos if (qctx->dns64) { 8754 1.1 christos qctx->client->query.attributes |= 8755 1.1 christos NS_QUERYATTR_DNS64; 8756 1.3 christos } 8757 1.3 christos if (qctx->dns64_exclude) { 8758 1.1 christos qctx->client->query.attributes |= 8759 1.1 christos NS_QUERYATTR_DNS64EXCLUDE; 8760 1.3 christos } 8761 1.13 christos } else if (query_usestale(qctx, result)) { 8762 1.13 christos /* 8763 1.13 christos * If serve-stale is enabled, query_usestale() 8764 1.13 christos * already set up 'qctx' for looking up a 8765 1.13 christos * stale response. 8766 1.13 christos */ 8767 1.23 christos return query_lookup(qctx); 8768 1.3 christos } else { 8769 1.3 christos QUERY_ERROR(qctx, result); 8770 1.3 christos } 8771 1.23 christos return ns_query_done(qctx); 8772 1.1 christos } else { 8773 1.1 christos /* Unable to give root server referral. */ 8774 1.9 christos CCTRACE(ISC_LOG_ERROR, "unable to give root server " 8775 1.9 christos "referral"); 8776 1.3 christos QUERY_ERROR(qctx, result); 8777 1.23 christos return ns_query_done(qctx); 8778 1.1 christos } 8779 1.1 christos } 8780 1.1 christos 8781 1.23 christos return query_delegation(qctx); 8782 1.3 christos 8783 1.9 christos cleanup: 8784 1.23 christos return result; 8785 1.3 christos } 8786 1.3 christos 8787 1.3 christos /*% 8788 1.3 christos * We have a delegation but recursion is not allowed, so return the delegation 8789 1.3 christos * to the client. 8790 1.3 christos */ 8791 1.3 christos static isc_result_t 8792 1.3 christos query_prepare_delegation_response(query_ctx_t *qctx) { 8793 1.20 christos isc_result_t result = ISC_R_UNSET; 8794 1.3 christos dns_rdataset_t **sigrdatasetp = NULL; 8795 1.3 christos bool detach = false; 8796 1.3 christos 8797 1.3 christos CALL_HOOK(NS_QUERY_PREP_DELEGATION_BEGIN, qctx); 8798 1.3 christos 8799 1.3 christos /* 8800 1.3 christos * qctx->fname could be released in query_addrrset(), so save a copy of 8801 1.3 christos * it here in case we need it. 8802 1.3 christos */ 8803 1.3 christos dns_fixedname_init(&qctx->dsname); 8804 1.20 christos dns_name_copy(qctx->fname, dns_fixedname_name(&qctx->dsname)); 8805 1.3 christos 8806 1.3 christos /* 8807 1.3 christos * This is the best answer. 8808 1.3 christos */ 8809 1.3 christos qctx->client->query.isreferral = true; 8810 1.3 christos 8811 1.3 christos if (!dns_db_iscache(qctx->db) && qctx->client->query.gluedb == NULL) { 8812 1.3 christos dns_db_attach(qctx->db, &qctx->client->query.gluedb); 8813 1.3 christos detach = true; 8814 1.3 christos } 8815 1.3 christos 8816 1.3 christos /* 8817 1.3 christos * We must ensure NOADDITIONAL is off, because the generation of 8818 1.3 christos * additional data is required in delegations. 8819 1.3 christos */ 8820 1.3 christos qctx->client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL; 8821 1.3 christos if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) { 8822 1.3 christos sigrdatasetp = &qctx->sigrdataset; 8823 1.3 christos } 8824 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp, 8825 1.9 christos qctx->dbuf, DNS_SECTION_AUTHORITY); 8826 1.3 christos if (detach) { 8827 1.3 christos dns_db_detach(&qctx->client->query.gluedb); 8828 1.3 christos } 8829 1.3 christos 8830 1.3 christos /* 8831 1.14 christos * Add DS/NSEC(3) record(s) if needed. 8832 1.3 christos */ 8833 1.3 christos query_addds(qctx); 8834 1.3 christos 8835 1.23 christos return ns_query_done(qctx); 8836 1.3 christos 8837 1.9 christos cleanup: 8838 1.23 christos return result; 8839 1.1 christos } 8840 1.1 christos 8841 1.1 christos /*% 8842 1.1 christos * Handle a delegation response from an authoritative lookup. This 8843 1.1 christos * may trigger additional lookups, e.g. from the cache database to 8844 1.1 christos * see if we have a better answer; if that is not allowed, return the 8845 1.3 christos * delegation to the client and call ns_query_done(). 8846 1.1 christos */ 8847 1.1 christos static isc_result_t 8848 1.1 christos query_zone_delegation(query_ctx_t *qctx) { 8849 1.20 christos isc_result_t result = ISC_R_UNSET; 8850 1.3 christos 8851 1.3 christos CALL_HOOK(NS_QUERY_ZONE_DELEGATION_BEGIN, qctx); 8852 1.1 christos 8853 1.1 christos /* 8854 1.1 christos * If the query type is DS, look to see if we are 8855 1.1 christos * authoritative for the child zone 8856 1.1 christos */ 8857 1.1 christos if (!RECURSIONOK(qctx->client) && 8858 1.23 christos (qctx->options.noexact && qctx->qtype == dns_rdatatype_ds)) 8859 1.1 christos { 8860 1.1 christos dns_db_t *tdb = NULL; 8861 1.1 christos dns_zone_t *tzone = NULL; 8862 1.1 christos dns_dbversion_t *tversion = NULL; 8863 1.23 christos dns_getdb_options_t options = { .partial = true }; 8864 1.23 christos result = query_getzonedb(qctx->client, 8865 1.23 christos qctx->client->query.qname, qctx->qtype, 8866 1.23 christos options, &tzone, &tdb, &tversion); 8867 1.1 christos if (result != ISC_R_SUCCESS) { 8868 1.9 christos if (tdb != NULL) { 8869 1.1 christos dns_db_detach(&tdb); 8870 1.9 christos } 8871 1.9 christos if (tzone != NULL) { 8872 1.1 christos dns_zone_detach(&tzone); 8873 1.9 christos } 8874 1.1 christos } else { 8875 1.23 christos qctx->options.noexact = false; 8876 1.9 christos ns_client_putrdataset(qctx->client, &qctx->rdataset); 8877 1.3 christos if (qctx->sigrdataset != NULL) { 8878 1.3 christos ns_client_putrdataset(qctx->client, 8879 1.3 christos &qctx->sigrdataset); 8880 1.3 christos } 8881 1.3 christos if (qctx->fname != NULL) { 8882 1.3 christos ns_client_releasename(qctx->client, 8883 1.3 christos &qctx->fname); 8884 1.3 christos } 8885 1.9 christos if (qctx->node != NULL) { 8886 1.9 christos dns_db_detachnode(qctx->db, &qctx->node); 8887 1.9 christos } 8888 1.9 christos if (qctx->db != NULL) { 8889 1.1 christos dns_db_detach(&qctx->db); 8890 1.9 christos } 8891 1.9 christos if (qctx->zone != NULL) { 8892 1.1 christos dns_zone_detach(&qctx->zone); 8893 1.9 christos } 8894 1.1 christos qctx->version = NULL; 8895 1.1 christos RESTORE(qctx->version, tversion); 8896 1.1 christos RESTORE(qctx->db, tdb); 8897 1.1 christos RESTORE(qctx->zone, tzone); 8898 1.3 christos qctx->authoritative = true; 8899 1.1 christos 8900 1.23 christos return query_lookup(qctx); 8901 1.1 christos } 8902 1.1 christos } 8903 1.1 christos 8904 1.3 christos if (USECACHE(qctx->client) && 8905 1.3 christos (RECURSIONOK(qctx->client) || 8906 1.3 christos (qctx->zone != NULL && 8907 1.3 christos dns_zone_gettype(qctx->zone) == dns_zone_mirror))) 8908 1.3 christos { 8909 1.1 christos /* 8910 1.1 christos * We might have a better answer or delegation in the 8911 1.1 christos * cache. We'll remember the current values of fname, 8912 1.1 christos * rdataset, and sigrdataset. We'll then go looking for 8913 1.1 christos * QNAME in the cache. If we find something better, we'll 8914 1.1 christos * use it instead. If not, then query_lookup() calls 8915 1.1 christos * query_notfound() which calls query_delegation(), and 8916 1.1 christos * we'll restore these values there. 8917 1.1 christos */ 8918 1.3 christos ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); 8919 1.1 christos SAVE(qctx->zdb, qctx->db); 8920 1.3 christos SAVE(qctx->znode, qctx->node); 8921 1.1 christos SAVE(qctx->zfname, qctx->fname); 8922 1.1 christos SAVE(qctx->zversion, qctx->version); 8923 1.1 christos SAVE(qctx->zrdataset, qctx->rdataset); 8924 1.1 christos SAVE(qctx->zsigrdataset, qctx->sigrdataset); 8925 1.3 christos dns_db_attach(qctx->view->cachedb, &qctx->db); 8926 1.3 christos qctx->is_zone = false; 8927 1.1 christos 8928 1.24 christos /* 8929 1.24 christos * Since 'qctx->is_zone' is now false, we should reconsider 8930 1.24 christos * setting the 'stalefirst' option, which is usually set in 8931 1.24 christos * the beginning in ns__query_start(). 8932 1.24 christos */ 8933 1.25 christos qctx->options.stalefirst = 8934 1.25 christos (qctx->view->staleanswerclienttimeout == 0 && 8935 1.25 christos dns_view_staleanswerenabled(qctx->view)); 8936 1.24 christos 8937 1.24 christos result = query_lookup(qctx); 8938 1.24 christos 8939 1.24 christos /* 8940 1.24 christos * After fetch completes, this option is not expected to be set. 8941 1.24 christos */ 8942 1.24 christos qctx->options.stalefirst = false; 8943 1.24 christos 8944 1.24 christos return result; 8945 1.1 christos } 8946 1.1 christos 8947 1.23 christos return query_prepare_delegation_response(qctx); 8948 1.1 christos 8949 1.9 christos cleanup: 8950 1.23 christos return result; 8951 1.1 christos } 8952 1.1 christos 8953 1.1 christos /*% 8954 1.1 christos * Handle delegation responses, including root referrals. 8955 1.1 christos * 8956 1.1 christos * If the delegation was returned from authoritative data, 8957 1.1 christos * call query_zone_delgation(). Otherwise, we can start 8958 1.1 christos * recursion if allowed; or else return the delegation to the 8959 1.3 christos * client and call ns_query_done(). 8960 1.1 christos */ 8961 1.1 christos static isc_result_t 8962 1.1 christos query_delegation(query_ctx_t *qctx) { 8963 1.20 christos isc_result_t result = ISC_R_UNSET; 8964 1.1 christos 8965 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_delegation"); 8966 1.9 christos 8967 1.3 christos CALL_HOOK(NS_QUERY_DELEGATION_BEGIN, qctx); 8968 1.3 christos 8969 1.3 christos qctx->authoritative = false; 8970 1.1 christos 8971 1.1 christos if (qctx->is_zone) { 8972 1.23 christos return query_zone_delegation(qctx); 8973 1.1 christos } 8974 1.1 christos 8975 1.1 christos if (qctx->zfname != NULL && 8976 1.1 christos (!dns_name_issubdomain(qctx->fname, qctx->zfname) || 8977 1.1 christos (qctx->is_staticstub_zone && 8978 1.1 christos dns_name_equal(qctx->fname, qctx->zfname)))) 8979 1.1 christos { 8980 1.1 christos /* 8981 1.1 christos * In the following cases use "authoritative" 8982 1.1 christos * data instead of the cache delegation: 8983 1.1 christos * 1. We've already got a delegation from 8984 1.1 christos * authoritative data, and it is better 8985 1.1 christos * than what we found in the cache. 8986 1.1 christos * (See the comment above.) 8987 1.1 christos * 2. The query name matches the origin name 8988 1.1 christos * of a static-stub zone. This needs to be 8989 1.1 christos * considered for the case where the NS of 8990 1.1 christos * the static-stub zone and the cached NS 8991 1.1 christos * are different. We still need to contact 8992 1.1 christos * the nameservers configured in the 8993 1.1 christos * static-stub zone. 8994 1.1 christos */ 8995 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 8996 1.1 christos 8997 1.1 christos /* 8998 1.3 christos * We've already done ns_client_keepname() on 8999 1.1 christos * qctx->zfname, so we must set dbuf to NULL to 9000 1.1 christos * prevent query_addrrset() from trying to 9001 1.3 christos * call ns_client_keepname() again. 9002 1.1 christos */ 9003 1.1 christos qctx->dbuf = NULL; 9004 1.3 christos ns_client_putrdataset(qctx->client, &qctx->rdataset); 9005 1.3 christos if (qctx->sigrdataset != NULL) { 9006 1.9 christos ns_client_putrdataset(qctx->client, &qctx->sigrdataset); 9007 1.3 christos } 9008 1.1 christos qctx->version = NULL; 9009 1.1 christos 9010 1.3 christos dns_db_detachnode(qctx->db, &qctx->node); 9011 1.3 christos dns_db_detach(&qctx->db); 9012 1.3 christos RESTORE(qctx->db, qctx->zdb); 9013 1.3 christos RESTORE(qctx->node, qctx->znode); 9014 1.1 christos RESTORE(qctx->fname, qctx->zfname); 9015 1.1 christos RESTORE(qctx->version, qctx->zversion); 9016 1.1 christos RESTORE(qctx->rdataset, qctx->zrdataset); 9017 1.1 christos RESTORE(qctx->sigrdataset, qctx->zsigrdataset); 9018 1.3 christos } 9019 1.1 christos 9020 1.3 christos result = query_delegation_recurse(qctx); 9021 1.3 christos if (result != ISC_R_COMPLETE) { 9022 1.23 christos return result; 9023 1.1 christos } 9024 1.1 christos 9025 1.23 christos return query_prepare_delegation_response(qctx); 9026 1.1 christos 9027 1.9 christos cleanup: 9028 1.23 christos return result; 9029 1.3 christos } 9030 1.1 christos 9031 1.3 christos /*% 9032 1.3 christos * Handle recursive queries that are triggered as part of the 9033 1.3 christos * delegation process. 9034 1.3 christos */ 9035 1.3 christos static isc_result_t 9036 1.3 christos query_delegation_recurse(query_ctx_t *qctx) { 9037 1.20 christos isc_result_t result = ISC_R_UNSET; 9038 1.3 christos dns_name_t *qname = qctx->client->query.qname; 9039 1.1 christos 9040 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_delegation_recurse"); 9041 1.9 christos 9042 1.3 christos if (!RECURSIONOK(qctx->client)) { 9043 1.23 christos return ISC_R_COMPLETE; 9044 1.1 christos } 9045 1.1 christos 9046 1.3 christos CALL_HOOK(NS_QUERY_DELEGATION_RECURSE_BEGIN, qctx); 9047 1.3 christos 9048 1.1 christos /* 9049 1.3 christos * We have a delegation and recursion is allowed, 9050 1.3 christos * so we call ns_query_recurse() to follow it. 9051 1.3 christos * This phase of the query processing is done; 9052 1.3 christos * we'll resume via fetch_callback() and 9053 1.3 christos * query_resume() when the recursion is complete. 9054 1.1 christos */ 9055 1.1 christos 9056 1.3 christos INSIST(!REDIRECT(qctx->client)); 9057 1.1 christos 9058 1.3 christos if (dns_rdatatype_atparent(qctx->type)) { 9059 1.3 christos /* 9060 1.3 christos * Parent is authoritative for this RDATA type (i.e. DS). 9061 1.3 christos */ 9062 1.3 christos result = ns_query_recurse(qctx->client, qctx->qtype, qname, 9063 1.3 christos NULL, NULL, qctx->resuming); 9064 1.3 christos } else if (qctx->dns64) { 9065 1.3 christos /* 9066 1.3 christos * Look up an A record so we can synthesize DNS64. 9067 1.3 christos */ 9068 1.3 christos result = ns_query_recurse(qctx->client, dns_rdatatype_a, qname, 9069 1.3 christos NULL, NULL, qctx->resuming); 9070 1.3 christos } else { 9071 1.3 christos /* 9072 1.3 christos * Any other recursion. 9073 1.3 christos */ 9074 1.3 christos result = ns_query_recurse(qctx->client, qctx->qtype, qname, 9075 1.3 christos qctx->fname, qctx->rdataset, 9076 1.3 christos qctx->resuming); 9077 1.1 christos } 9078 1.1 christos 9079 1.3 christos if (result == ISC_R_SUCCESS) { 9080 1.3 christos qctx->client->query.attributes |= NS_QUERYATTR_RECURSING; 9081 1.3 christos if (qctx->dns64) { 9082 1.3 christos qctx->client->query.attributes |= NS_QUERYATTR_DNS64; 9083 1.3 christos } 9084 1.3 christos if (qctx->dns64_exclude) { 9085 1.3 christos qctx->client->query.attributes |= 9086 1.9 christos NS_QUERYATTR_DNS64EXCLUDE; 9087 1.3 christos } 9088 1.13 christos } else if (query_usestale(qctx, result)) { 9089 1.13 christos /* 9090 1.13 christos * If serve-stale is enabled, query_usestale() already set up 9091 1.13 christos * 'qctx' for looking up a stale response. 9092 1.13 christos */ 9093 1.23 christos return query_lookup(qctx); 9094 1.3 christos } else { 9095 1.3 christos QUERY_ERROR(qctx, result); 9096 1.1 christos } 9097 1.1 christos 9098 1.23 christos return ns_query_done(qctx); 9099 1.1 christos 9100 1.9 christos cleanup: 9101 1.23 christos return result; 9102 1.1 christos } 9103 1.1 christos 9104 1.1 christos /*% 9105 1.14 christos * Add DS/NSEC(3) record(s) if needed. 9106 1.1 christos */ 9107 1.1 christos static void 9108 1.1 christos query_addds(query_ctx_t *qctx) { 9109 1.1 christos ns_client_t *client = qctx->client; 9110 1.1 christos dns_fixedname_t fixed; 9111 1.1 christos dns_name_t *fname = NULL; 9112 1.1 christos dns_name_t *rname = NULL; 9113 1.1 christos dns_name_t *name; 9114 1.1 christos dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 9115 1.1 christos isc_buffer_t *dbuf, b; 9116 1.1 christos isc_result_t result; 9117 1.1 christos unsigned int count; 9118 1.1 christos 9119 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addds"); 9120 1.1 christos 9121 1.1 christos /* 9122 1.1 christos * DS not needed. 9123 1.1 christos */ 9124 1.1 christos if (!WANTDNSSEC(client)) { 9125 1.1 christos return; 9126 1.1 christos } 9127 1.1 christos 9128 1.1 christos /* 9129 1.1 christos * We'll need some resources... 9130 1.1 christos */ 9131 1.3 christos rdataset = ns_client_newrdataset(client); 9132 1.3 christos sigrdataset = ns_client_newrdataset(client); 9133 1.1 christos 9134 1.1 christos /* 9135 1.1 christos * Look for the DS record, which may or may not be present. 9136 1.1 christos */ 9137 1.1 christos result = dns_db_findrdataset(qctx->db, qctx->node, qctx->version, 9138 1.9 christos dns_rdatatype_ds, 0, client->now, rdataset, 9139 1.9 christos sigrdataset); 9140 1.1 christos /* 9141 1.1 christos * If we didn't find it, look for an NSEC. 9142 1.1 christos */ 9143 1.9 christos if (result == ISC_R_NOTFOUND) { 9144 1.9 christos result = dns_db_findrdataset( 9145 1.9 christos qctx->db, qctx->node, qctx->version, dns_rdatatype_nsec, 9146 1.9 christos 0, client->now, rdataset, sigrdataset); 9147 1.9 christos } 9148 1.9 christos if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { 9149 1.1 christos goto addnsec3; 9150 1.9 christos } 9151 1.1 christos if (!dns_rdataset_isassociated(rdataset) || 9152 1.1 christos !dns_rdataset_isassociated(sigrdataset)) 9153 1.9 christos { 9154 1.1 christos goto addnsec3; 9155 1.9 christos } 9156 1.1 christos 9157 1.1 christos /* 9158 1.1 christos * We've already added the NS record, so if the name's not there, 9159 1.14 christos * we have other problems. 9160 1.1 christos */ 9161 1.1 christos result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY); 9162 1.9 christos if (result != ISC_R_SUCCESS) { 9163 1.1 christos goto cleanup; 9164 1.9 christos } 9165 1.1 christos 9166 1.14 christos /* 9167 1.14 christos * Find the delegation in the response message - it is not necessarily 9168 1.14 christos * the first name in the AUTHORITY section when wildcard processing is 9169 1.14 christos * involved. 9170 1.14 christos */ 9171 1.14 christos while (result == ISC_R_SUCCESS) { 9172 1.14 christos rname = NULL; 9173 1.14 christos dns_message_currentname(client->message, DNS_SECTION_AUTHORITY, 9174 1.14 christos &rname); 9175 1.14 christos result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL); 9176 1.14 christos if (result == ISC_R_SUCCESS) { 9177 1.14 christos break; 9178 1.14 christos } 9179 1.14 christos result = dns_message_nextname(client->message, 9180 1.14 christos DNS_SECTION_AUTHORITY); 9181 1.14 christos } 9182 1.14 christos 9183 1.9 christos if (result != ISC_R_SUCCESS) { 9184 1.1 christos goto cleanup; 9185 1.9 christos } 9186 1.1 christos 9187 1.14 christos /* 9188 1.14 christos * Add the relevant RRset (DS or NSEC) to the delegation. 9189 1.14 christos */ 9190 1.14 christos query_addrrset(qctx, &rname, &rdataset, &sigrdataset, NULL, 9191 1.14 christos DNS_SECTION_AUTHORITY); 9192 1.14 christos goto cleanup; 9193 1.1 christos 9194 1.9 christos addnsec3: 9195 1.9 christos if (!dns_db_iszone(qctx->db)) { 9196 1.1 christos goto cleanup; 9197 1.9 christos } 9198 1.1 christos /* 9199 1.1 christos * Add the NSEC3 which proves the DS does not exist. 9200 1.1 christos */ 9201 1.3 christos dbuf = ns_client_getnamebuf(client); 9202 1.3 christos fname = ns_client_newname(client, dbuf, &b); 9203 1.1 christos dns_fixedname_init(&fixed); 9204 1.9 christos if (dns_rdataset_isassociated(rdataset)) { 9205 1.1 christos dns_rdataset_disassociate(rdataset); 9206 1.9 christos } 9207 1.9 christos if (dns_rdataset_isassociated(sigrdataset)) { 9208 1.1 christos dns_rdataset_disassociate(sigrdataset); 9209 1.9 christos } 9210 1.1 christos name = dns_fixedname_name(&qctx->dsname); 9211 1.1 christos query_findclosestnsec3(name, qctx->db, qctx->version, client, rdataset, 9212 1.3 christos sigrdataset, fname, true, 9213 1.1 christos dns_fixedname_name(&fixed)); 9214 1.9 christos if (!dns_rdataset_isassociated(rdataset)) { 9215 1.1 christos goto cleanup; 9216 1.9 christos } 9217 1.3 christos query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf, 9218 1.1 christos DNS_SECTION_AUTHORITY); 9219 1.1 christos /* 9220 1.1 christos * Did we find the closest provable encloser instead? 9221 1.1 christos * If so add the nearest to the closest provable encloser. 9222 1.1 christos */ 9223 1.1 christos if (!dns_name_equal(name, dns_fixedname_name(&fixed))) { 9224 1.1 christos count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1; 9225 1.1 christos dns_name_getlabelsequence(name, 9226 1.1 christos dns_name_countlabels(name) - count, 9227 1.1 christos count, dns_fixedname_name(&fixed)); 9228 1.1 christos fixfname(client, &fname, &dbuf, &b); 9229 1.1 christos fixrdataset(client, &rdataset); 9230 1.1 christos fixrdataset(client, &sigrdataset); 9231 1.9 christos if (fname == NULL || rdataset == NULL || sigrdataset == NULL) { 9232 1.9 christos goto cleanup; 9233 1.9 christos } 9234 1.9 christos query_findclosestnsec3(dns_fixedname_name(&fixed), qctx->db, 9235 1.9 christos qctx->version, client, rdataset, 9236 1.9 christos sigrdataset, fname, false, NULL); 9237 1.9 christos if (!dns_rdataset_isassociated(rdataset)) { 9238 1.1 christos goto cleanup; 9239 1.9 christos } 9240 1.3 christos query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf, 9241 1.1 christos DNS_SECTION_AUTHORITY); 9242 1.1 christos } 9243 1.1 christos 9244 1.9 christos cleanup: 9245 1.3 christos if (rdataset != NULL) { 9246 1.3 christos ns_client_putrdataset(client, &rdataset); 9247 1.3 christos } 9248 1.3 christos if (sigrdataset != NULL) { 9249 1.3 christos ns_client_putrdataset(client, &sigrdataset); 9250 1.3 christos } 9251 1.3 christos if (fname != NULL) { 9252 1.3 christos ns_client_releasename(client, &fname); 9253 1.3 christos } 9254 1.1 christos } 9255 1.1 christos 9256 1.1 christos /*% 9257 1.1 christos * Handle authoritative NOERROR/NODATA responses. 9258 1.1 christos */ 9259 1.1 christos static isc_result_t 9260 1.3 christos query_nodata(query_ctx_t *qctx, isc_result_t res) { 9261 1.3 christos isc_result_t result = res; 9262 1.3 christos 9263 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_nodata"); 9264 1.9 christos 9265 1.3 christos CALL_HOOK(NS_QUERY_NODATA_BEGIN, qctx); 9266 1.3 christos 9267 1.1 christos #ifdef dns64_bis_return_excluded_addresses 9268 1.1 christos if (qctx->dns64) 9269 1.9 christos #else /* ifdef dns64_bis_return_excluded_addresses */ 9270 1.1 christos if (qctx->dns64 && !qctx->dns64_exclude) 9271 1.9 christos #endif /* ifdef dns64_bis_return_excluded_addresses */ 9272 1.1 christos { 9273 1.1 christos isc_buffer_t b; 9274 1.1 christos /* 9275 1.1 christos * Restore the answers from the previous AAAA lookup. 9276 1.1 christos */ 9277 1.9 christos if (qctx->rdataset != NULL) { 9278 1.3 christos ns_client_putrdataset(qctx->client, &qctx->rdataset); 9279 1.9 christos } 9280 1.9 christos if (qctx->sigrdataset != NULL) { 9281 1.3 christos ns_client_putrdataset(qctx->client, &qctx->sigrdataset); 9282 1.9 christos } 9283 1.1 christos RESTORE(qctx->rdataset, qctx->client->query.dns64_aaaa); 9284 1.1 christos RESTORE(qctx->sigrdataset, qctx->client->query.dns64_sigaaaa); 9285 1.1 christos if (qctx->fname == NULL) { 9286 1.3 christos qctx->dbuf = ns_client_getnamebuf(qctx->client); 9287 1.3 christos qctx->fname = ns_client_newname(qctx->client, 9288 1.3 christos qctx->dbuf, &b); 9289 1.1 christos } 9290 1.20 christos dns_name_copy(qctx->client->query.qname, qctx->fname); 9291 1.3 christos qctx->dns64 = false; 9292 1.1 christos #ifdef dns64_bis_return_excluded_addresses 9293 1.1 christos /* 9294 1.1 christos * Resume the diverted processing of the AAAA response? 9295 1.1 christos */ 9296 1.9 christos if (qctx->dns64_exclude) { 9297 1.23 christos return query_prepresponse(qctx); 9298 1.9 christos } 9299 1.9 christos #endif /* ifdef dns64_bis_return_excluded_addresses */ 9300 1.9 christos } else if ((result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) && 9301 1.9 christos !ISC_LIST_EMPTY(qctx->view->dns64) && !qctx->nxrewrite && 9302 1.1 christos qctx->client->message->rdclass == dns_rdataclass_in && 9303 1.1 christos qctx->qtype == dns_rdatatype_aaaa) 9304 1.1 christos { 9305 1.1 christos /* 9306 1.1 christos * Look to see if there are A records for this name. 9307 1.1 christos */ 9308 1.1 christos switch (result) { 9309 1.1 christos case DNS_R_NCACHENXRRSET: 9310 1.1 christos /* 9311 1.1 christos * This is from the negative cache; if the ttl is 9312 1.1 christos * zero, we need to work out whether we have just 9313 1.1 christos * decremented to zero or there was no negative 9314 1.1 christos * cache ttl in the answer. 9315 1.1 christos */ 9316 1.1 christos if (qctx->rdataset->ttl != 0) { 9317 1.1 christos qctx->client->query.dns64_ttl = 9318 1.1 christos qctx->rdataset->ttl; 9319 1.1 christos break; 9320 1.1 christos } 9321 1.1 christos if (dns_rdataset_first(qctx->rdataset) == ISC_R_SUCCESS) 9322 1.9 christos { 9323 1.1 christos qctx->client->query.dns64_ttl = 0; 9324 1.9 christos } 9325 1.1 christos break; 9326 1.1 christos case DNS_R_NXRRSET: 9327 1.1 christos qctx->client->query.dns64_ttl = 9328 1.1 christos dns64_ttl(qctx->db, qctx->version); 9329 1.1 christos break; 9330 1.1 christos default: 9331 1.15 christos UNREACHABLE(); 9332 1.1 christos } 9333 1.1 christos 9334 1.1 christos SAVE(qctx->client->query.dns64_aaaa, qctx->rdataset); 9335 1.1 christos SAVE(qctx->client->query.dns64_sigaaaa, qctx->sigrdataset); 9336 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 9337 1.1 christos dns_db_detachnode(qctx->db, &qctx->node); 9338 1.1 christos qctx->type = qctx->qtype = dns_rdatatype_a; 9339 1.3 christos qctx->dns64 = true; 9340 1.23 christos return query_lookup(qctx); 9341 1.1 christos } 9342 1.1 christos 9343 1.1 christos if (qctx->is_zone) { 9344 1.23 christos return query_sign_nodata(qctx); 9345 1.1 christos } else { 9346 1.1 christos /* 9347 1.1 christos * We don't call query_addrrset() because we don't need any 9348 1.1 christos * of its extra features (and things would probably break!). 9349 1.1 christos */ 9350 1.1 christos if (dns_rdataset_isassociated(qctx->rdataset)) { 9351 1.3 christos ns_client_keepname(qctx->client, qctx->fname, 9352 1.3 christos qctx->dbuf); 9353 1.9 christos dns_message_addname(qctx->client->message, qctx->fname, 9354 1.1 christos DNS_SECTION_AUTHORITY); 9355 1.9 christos ISC_LIST_APPEND(qctx->fname->list, qctx->rdataset, 9356 1.9 christos link); 9357 1.1 christos qctx->fname = NULL; 9358 1.1 christos qctx->rdataset = NULL; 9359 1.1 christos } 9360 1.1 christos } 9361 1.1 christos 9362 1.23 christos return ns_query_done(qctx); 9363 1.3 christos 9364 1.9 christos cleanup: 9365 1.23 christos return result; 9366 1.1 christos } 9367 1.1 christos 9368 1.1 christos /*% 9369 1.1 christos * Add RRSIGs for NOERROR/NODATA responses when answering authoritatively. 9370 1.1 christos */ 9371 1.1 christos isc_result_t 9372 1.1 christos query_sign_nodata(query_ctx_t *qctx) { 9373 1.1 christos isc_result_t result; 9374 1.9 christos 9375 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_sign_nodata"); 9376 1.9 christos 9377 1.1 christos /* 9378 1.1 christos * Look for a NSEC3 record if we don't have a NSEC record. 9379 1.1 christos */ 9380 1.9 christos if (qctx->redirected) { 9381 1.23 christos return ns_query_done(qctx); 9382 1.9 christos } 9383 1.1 christos if (!dns_rdataset_isassociated(qctx->rdataset) && 9384 1.16 christos WANTDNSSEC(qctx->client)) 9385 1.16 christos { 9386 1.23 christos if (!qctx->fname->attributes.wildcard) { 9387 1.1 christos dns_name_t *found; 9388 1.1 christos dns_name_t *qname; 9389 1.1 christos dns_fixedname_t fixed; 9390 1.1 christos isc_buffer_t b; 9391 1.1 christos 9392 1.1 christos found = dns_fixedname_initname(&fixed); 9393 1.1 christos qname = qctx->client->query.qname; 9394 1.1 christos 9395 1.1 christos query_findclosestnsec3(qname, qctx->db, qctx->version, 9396 1.1 christos qctx->client, qctx->rdataset, 9397 1.1 christos qctx->sigrdataset, qctx->fname, 9398 1.3 christos true, found); 9399 1.1 christos /* 9400 1.1 christos * Did we find the closest provable encloser 9401 1.1 christos * instead? If so add the nearest to the 9402 1.1 christos * closest provable encloser. 9403 1.1 christos */ 9404 1.1 christos if (dns_rdataset_isassociated(qctx->rdataset) && 9405 1.1 christos !dns_name_equal(qname, found) && 9406 1.23 christos (((qctx->client->manager->sctx->options & 9407 1.1 christos NS_SERVER_NONEAREST) == 0) || 9408 1.1 christos qctx->qtype == dns_rdatatype_ds)) 9409 1.1 christos { 9410 1.1 christos unsigned int count; 9411 1.1 christos unsigned int skip; 9412 1.1 christos 9413 1.1 christos /* 9414 1.1 christos * Add the closest provable encloser. 9415 1.1 christos */ 9416 1.3 christos query_addrrset(qctx, &qctx->fname, 9417 1.1 christos &qctx->rdataset, 9418 1.9 christos &qctx->sigrdataset, qctx->dbuf, 9419 1.1 christos DNS_SECTION_AUTHORITY); 9420 1.1 christos 9421 1.9 christos count = dns_name_countlabels(found) + 1; 9422 1.9 christos skip = dns_name_countlabels(qname) - count; 9423 1.9 christos dns_name_getlabelsequence(qname, skip, count, 9424 1.1 christos found); 9425 1.1 christos 9426 1.1 christos fixfname(qctx->client, &qctx->fname, 9427 1.1 christos &qctx->dbuf, &b); 9428 1.1 christos fixrdataset(qctx->client, &qctx->rdataset); 9429 1.1 christos fixrdataset(qctx->client, &qctx->sigrdataset); 9430 1.1 christos if (qctx->fname == NULL || 9431 1.1 christos qctx->rdataset == NULL || 9432 1.16 christos qctx->sigrdataset == NULL) 9433 1.16 christos { 9434 1.9 christos CCTRACE(ISC_LOG_ERROR, "query_sign_" 9435 1.9 christos "nodata: " 9436 1.9 christos "failure " 9437 1.9 christos "getting " 9438 1.9 christos "closest " 9439 1.9 christos "encloser"); 9440 1.3 christos QUERY_ERROR(qctx, ISC_R_NOMEMORY); 9441 1.23 christos return ns_query_done(qctx); 9442 1.1 christos } 9443 1.1 christos /* 9444 1.1 christos * 'nearest' doesn't exist so 9445 1.3 christos * 'exist' is set to false. 9446 1.1 christos */ 9447 1.9 christos query_findclosestnsec3( 9448 1.9 christos found, qctx->db, qctx->version, 9449 1.9 christos qctx->client, qctx->rdataset, 9450 1.9 christos qctx->sigrdataset, qctx->fname, false, 9451 1.9 christos NULL); 9452 1.1 christos } 9453 1.1 christos } else { 9454 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 9455 1.3 christos query_addwildcardproof(qctx, false, true); 9456 1.1 christos } 9457 1.1 christos } 9458 1.1 christos if (dns_rdataset_isassociated(qctx->rdataset)) { 9459 1.1 christos /* 9460 1.1 christos * If we've got a NSEC record, we need to save the 9461 1.1 christos * name now because we're going call query_addsoa() 9462 1.1 christos * below, and it needs to use the name buffer. 9463 1.1 christos */ 9464 1.3 christos ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); 9465 1.1 christos } else if (qctx->fname != NULL) { 9466 1.1 christos /* 9467 1.1 christos * We're not going to use fname, and need to release 9468 1.1 christos * our hold on the name buffer so query_addsoa() 9469 1.1 christos * may use it. 9470 1.1 christos */ 9471 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 9472 1.1 christos } 9473 1.1 christos 9474 1.1 christos /* 9475 1.1 christos * The RPZ SOA has already been added to the additional section 9476 1.1 christos * if this was an RPZ rewrite, but if it wasn't, add it now. 9477 1.1 christos */ 9478 1.1 christos if (!qctx->nxrewrite) { 9479 1.9 christos result = query_addsoa(qctx, UINT32_MAX, DNS_SECTION_AUTHORITY); 9480 1.1 christos if (result != ISC_R_SUCCESS) { 9481 1.1 christos QUERY_ERROR(qctx, result); 9482 1.23 christos return ns_query_done(qctx); 9483 1.1 christos } 9484 1.1 christos } 9485 1.1 christos 9486 1.1 christos /* 9487 1.1 christos * Add NSEC record if we found one. 9488 1.1 christos */ 9489 1.1 christos if (WANTDNSSEC(qctx->client) && 9490 1.16 christos dns_rdataset_isassociated(qctx->rdataset)) 9491 1.16 christos { 9492 1.1 christos query_addnxrrsetnsec(qctx); 9493 1.1 christos } 9494 1.1 christos 9495 1.23 christos return ns_query_done(qctx); 9496 1.1 christos } 9497 1.1 christos 9498 1.1 christos static void 9499 1.1 christos query_addnxrrsetnsec(query_ctx_t *qctx) { 9500 1.1 christos ns_client_t *client = qctx->client; 9501 1.1 christos dns_rdata_t sigrdata; 9502 1.1 christos dns_rdata_rrsig_t sig; 9503 1.1 christos unsigned int labels; 9504 1.1 christos isc_buffer_t *dbuf, b; 9505 1.1 christos dns_name_t *fname; 9506 1.3 christos isc_result_t result; 9507 1.1 christos 9508 1.1 christos INSIST(qctx->fname != NULL); 9509 1.1 christos 9510 1.23 christos if (!qctx->fname->attributes.wildcard) { 9511 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, 9512 1.9 christos &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY); 9513 1.1 christos return; 9514 1.1 christos } 9515 1.1 christos 9516 1.1 christos if (qctx->sigrdataset == NULL || 9517 1.16 christos !dns_rdataset_isassociated(qctx->sigrdataset)) 9518 1.16 christos { 9519 1.1 christos return; 9520 1.1 christos } 9521 1.1 christos 9522 1.1 christos if (dns_rdataset_first(qctx->sigrdataset) != ISC_R_SUCCESS) { 9523 1.1 christos return; 9524 1.1 christos } 9525 1.1 christos 9526 1.1 christos dns_rdata_init(&sigrdata); 9527 1.1 christos dns_rdataset_current(qctx->sigrdataset, &sigrdata); 9528 1.3 christos result = dns_rdata_tostruct(&sigrdata, &sig, NULL); 9529 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 9530 1.1 christos 9531 1.1 christos labels = dns_name_countlabels(qctx->fname); 9532 1.1 christos if ((unsigned int)sig.labels + 1 >= labels) { 9533 1.1 christos return; 9534 1.1 christos } 9535 1.1 christos 9536 1.3 christos query_addwildcardproof(qctx, true, false); 9537 1.1 christos 9538 1.1 christos /* 9539 1.1 christos * We'll need some resources... 9540 1.1 christos */ 9541 1.3 christos dbuf = ns_client_getnamebuf(client); 9542 1.3 christos fname = ns_client_newname(client, dbuf, &b); 9543 1.1 christos 9544 1.1 christos dns_name_split(qctx->fname, sig.labels + 1, NULL, fname); 9545 1.1 christos /* This will succeed, since we've stripped labels. */ 9546 1.1 christos RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname, 9547 1.1 christos NULL) == ISC_R_SUCCESS); 9548 1.9 christos query_addrrset(qctx, &fname, &qctx->rdataset, &qctx->sigrdataset, dbuf, 9549 1.9 christos DNS_SECTION_AUTHORITY); 9550 1.1 christos } 9551 1.1 christos 9552 1.1 christos /*% 9553 1.1 christos * Handle NXDOMAIN and empty wildcard responses. 9554 1.1 christos */ 9555 1.1 christos static isc_result_t 9556 1.18 christos query_nxdomain(query_ctx_t *qctx, isc_result_t result) { 9557 1.1 christos dns_section_t section; 9558 1.3 christos uint32_t ttl; 9559 1.18 christos bool empty_wild = (result == DNS_R_EMPTYWILD); 9560 1.1 christos 9561 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_nxdomain"); 9562 1.9 christos 9563 1.3 christos CALL_HOOK(NS_QUERY_NXDOMAIN_BEGIN, qctx); 9564 1.3 christos 9565 1.1 christos INSIST(qctx->is_zone || REDIRECT(qctx->client)); 9566 1.1 christos 9567 1.1 christos if (!empty_wild) { 9568 1.18 christos result = query_redirect(qctx, result); 9569 1.9 christos if (result != ISC_R_COMPLETE) { 9570 1.23 christos return result; 9571 1.9 christos } 9572 1.1 christos } 9573 1.1 christos 9574 1.1 christos if (dns_rdataset_isassociated(qctx->rdataset)) { 9575 1.1 christos /* 9576 1.1 christos * If we've got a NSEC record, we need to save the 9577 1.1 christos * name now because we're going call query_addsoa() 9578 1.1 christos * below, and it needs to use the name buffer. 9579 1.1 christos */ 9580 1.3 christos ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); 9581 1.1 christos } else if (qctx->fname != NULL) { 9582 1.1 christos /* 9583 1.1 christos * We're not going to use fname, and need to release 9584 1.1 christos * our hold on the name buffer so query_addsoa() 9585 1.1 christos * may use it. 9586 1.1 christos */ 9587 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 9588 1.1 christos } 9589 1.1 christos 9590 1.1 christos /* 9591 1.1 christos * Add SOA to the additional section if generated by a 9592 1.1 christos * RPZ rewrite. 9593 1.1 christos * 9594 1.1 christos * If the query was for a SOA record force the 9595 1.1 christos * ttl to zero so that it is possible for clients to find 9596 1.1 christos * the containing zone of an arbitrary name with a stub 9597 1.1 christos * resolver and not have it cached. 9598 1.1 christos */ 9599 1.1 christos section = qctx->nxrewrite ? DNS_SECTION_ADDITIONAL 9600 1.1 christos : DNS_SECTION_AUTHORITY; 9601 1.3 christos ttl = UINT32_MAX; 9602 1.1 christos if (!qctx->nxrewrite && qctx->qtype == dns_rdatatype_soa && 9603 1.1 christos qctx->zone != NULL && dns_zone_getzeronosoattl(qctx->zone)) 9604 1.1 christos { 9605 1.1 christos ttl = 0; 9606 1.1 christos } 9607 1.16 christos if (!qctx->nxrewrite || 9608 1.16 christos (qctx->rpz_st != NULL && qctx->rpz_st->m.rpz->addsoa)) 9609 1.16 christos { 9610 1.5 christos result = query_addsoa(qctx, ttl, section); 9611 1.5 christos if (result != ISC_R_SUCCESS) { 9612 1.5 christos QUERY_ERROR(qctx, result); 9613 1.23 christos return ns_query_done(qctx); 9614 1.5 christos } 9615 1.1 christos } 9616 1.1 christos 9617 1.1 christos if (WANTDNSSEC(qctx->client)) { 9618 1.1 christos /* 9619 1.1 christos * Add NSEC record if we found one. 9620 1.1 christos */ 9621 1.9 christos if (dns_rdataset_isassociated(qctx->rdataset)) { 9622 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, 9623 1.9 christos &qctx->sigrdataset, NULL, 9624 1.9 christos DNS_SECTION_AUTHORITY); 9625 1.9 christos } 9626 1.3 christos query_addwildcardproof(qctx, false, false); 9627 1.1 christos } 9628 1.1 christos 9629 1.1 christos /* 9630 1.1 christos * Set message rcode. 9631 1.1 christos */ 9632 1.9 christos if (empty_wild) { 9633 1.1 christos qctx->client->message->rcode = dns_rcode_noerror; 9634 1.9 christos } else { 9635 1.1 christos qctx->client->message->rcode = dns_rcode_nxdomain; 9636 1.9 christos } 9637 1.1 christos 9638 1.23 christos return ns_query_done(qctx); 9639 1.3 christos 9640 1.9 christos cleanup: 9641 1.23 christos return result; 9642 1.1 christos } 9643 1.1 christos 9644 1.1 christos /* 9645 1.1 christos * Handle both types of NXDOMAIN redirection, calling redirect() 9646 1.1 christos * (which implements type redirect zones) and redirect2() (which 9647 1.1 christos * implements recursive nxdomain-redirect lookups). 9648 1.1 christos * 9649 1.1 christos * Any result code other than ISC_R_COMPLETE means redirection was 9650 1.1 christos * successful and the result code should be returned up the call stack. 9651 1.1 christos * 9652 1.1 christos * ISC_R_COMPLETE means we reached the end of this function without 9653 1.1 christos * redirecting, so query processing should continue past it. 9654 1.1 christos */ 9655 1.1 christos static isc_result_t 9656 1.18 christos query_redirect(query_ctx_t *qctx, isc_result_t saved_result) { 9657 1.1 christos isc_result_t result; 9658 1.1 christos 9659 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_redirect"); 9660 1.9 christos 9661 1.1 christos result = redirect(qctx->client, qctx->fname, qctx->rdataset, 9662 1.9 christos &qctx->node, &qctx->db, &qctx->version, qctx->type); 9663 1.1 christos switch (result) { 9664 1.1 christos case ISC_R_SUCCESS: 9665 1.9 christos inc_stats(qctx->client, ns_statscounter_nxdomainredirect); 9666 1.23 christos return query_prepresponse(qctx); 9667 1.1 christos case DNS_R_NXRRSET: 9668 1.3 christos qctx->redirected = true; 9669 1.3 christos qctx->is_zone = true; 9670 1.23 christos return query_nodata(qctx, DNS_R_NXRRSET); 9671 1.1 christos case DNS_R_NCACHENXRRSET: 9672 1.3 christos qctx->redirected = true; 9673 1.3 christos qctx->is_zone = false; 9674 1.23 christos return query_ncache(qctx, DNS_R_NCACHENXRRSET); 9675 1.1 christos default: 9676 1.1 christos break; 9677 1.1 christos } 9678 1.1 christos 9679 1.1 christos result = redirect2(qctx->client, qctx->fname, qctx->rdataset, 9680 1.9 christos &qctx->node, &qctx->db, &qctx->version, qctx->type, 9681 1.9 christos &qctx->is_zone); 9682 1.1 christos switch (result) { 9683 1.1 christos case ISC_R_SUCCESS: 9684 1.9 christos inc_stats(qctx->client, ns_statscounter_nxdomainredirect); 9685 1.23 christos return query_prepresponse(qctx); 9686 1.1 christos case DNS_R_CONTINUE: 9687 1.1 christos inc_stats(qctx->client, 9688 1.1 christos ns_statscounter_nxdomainredirect_rlookup); 9689 1.1 christos SAVE(qctx->client->query.redirect.db, qctx->db); 9690 1.1 christos SAVE(qctx->client->query.redirect.node, qctx->node); 9691 1.1 christos SAVE(qctx->client->query.redirect.zone, qctx->zone); 9692 1.1 christos qctx->client->query.redirect.qtype = qctx->qtype; 9693 1.1 christos INSIST(qctx->rdataset != NULL); 9694 1.1 christos SAVE(qctx->client->query.redirect.rdataset, qctx->rdataset); 9695 1.1 christos SAVE(qctx->client->query.redirect.sigrdataset, 9696 1.1 christos qctx->sigrdataset); 9697 1.18 christos qctx->client->query.redirect.result = saved_result; 9698 1.20 christos dns_name_copy(qctx->fname, qctx->client->query.redirect.fname); 9699 1.1 christos qctx->client->query.redirect.authoritative = 9700 1.1 christos qctx->authoritative; 9701 1.1 christos qctx->client->query.redirect.is_zone = qctx->is_zone; 9702 1.23 christos return ns_query_done(qctx); 9703 1.1 christos case DNS_R_NXRRSET: 9704 1.3 christos qctx->redirected = true; 9705 1.3 christos qctx->is_zone = true; 9706 1.23 christos return query_nodata(qctx, DNS_R_NXRRSET); 9707 1.1 christos case DNS_R_NCACHENXRRSET: 9708 1.3 christos qctx->redirected = true; 9709 1.3 christos qctx->is_zone = false; 9710 1.23 christos return query_ncache(qctx, DNS_R_NCACHENXRRSET); 9711 1.1 christos default: 9712 1.1 christos break; 9713 1.1 christos } 9714 1.1 christos 9715 1.23 christos return ISC_R_COMPLETE; 9716 1.1 christos } 9717 1.1 christos 9718 1.1 christos /*% 9719 1.1 christos * Logging function to be passed to dns_nsec_noexistnodata. 9720 1.1 christos */ 9721 1.1 christos static void 9722 1.1 christos log_noexistnodata(void *val, int level, const char *fmt, ...) { 9723 1.1 christos query_ctx_t *qctx = val; 9724 1.1 christos va_list ap; 9725 1.1 christos 9726 1.1 christos va_start(ap, fmt); 9727 1.9 christos ns_client_logv(qctx->client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, 9728 1.9 christos level, fmt, ap); 9729 1.1 christos va_end(ap); 9730 1.1 christos } 9731 1.1 christos 9732 1.1 christos static dns_ttl_t 9733 1.1 christos query_synthttl(dns_rdataset_t *soardataset, dns_rdataset_t *sigsoardataset, 9734 1.1 christos dns_rdataset_t *p1rdataset, dns_rdataset_t *sigp1rdataset, 9735 1.9 christos dns_rdataset_t *p2rdataset, dns_rdataset_t *sigp2rdataset) { 9736 1.1 christos dns_rdata_soa_t soa; 9737 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 9738 1.1 christos dns_ttl_t ttl; 9739 1.1 christos isc_result_t result; 9740 1.1 christos 9741 1.1 christos REQUIRE(soardataset != NULL); 9742 1.1 christos REQUIRE(sigsoardataset != NULL); 9743 1.1 christos REQUIRE(p1rdataset != NULL); 9744 1.1 christos REQUIRE(sigp1rdataset != NULL); 9745 1.1 christos 9746 1.1 christos result = dns_rdataset_first(soardataset); 9747 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 9748 1.1 christos dns_rdataset_current(soardataset, &rdata); 9749 1.3 christos result = dns_rdata_tostruct(&rdata, &soa, NULL); 9750 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 9751 1.1 christos 9752 1.1 christos ttl = ISC_MIN(soa.minimum, soardataset->ttl); 9753 1.1 christos ttl = ISC_MIN(ttl, sigsoardataset->ttl); 9754 1.1 christos ttl = ISC_MIN(ttl, p1rdataset->ttl); 9755 1.1 christos ttl = ISC_MIN(ttl, sigp1rdataset->ttl); 9756 1.9 christos if (p2rdataset != NULL) { 9757 1.1 christos ttl = ISC_MIN(ttl, p2rdataset->ttl); 9758 1.9 christos } 9759 1.9 christos if (sigp2rdataset != NULL) { 9760 1.1 christos ttl = ISC_MIN(ttl, sigp2rdataset->ttl); 9761 1.9 christos } 9762 1.1 christos 9763 1.23 christos return ttl; 9764 1.1 christos } 9765 1.1 christos 9766 1.1 christos /* 9767 1.1 christos * Synthesize a NODATA response from the SOA and covering NSEC in cache. 9768 1.1 christos */ 9769 1.1 christos static isc_result_t 9770 1.1 christos query_synthnodata(query_ctx_t *qctx, const dns_name_t *signer, 9771 1.1 christos dns_rdataset_t **soardatasetp, 9772 1.9 christos dns_rdataset_t **sigsoardatasetp) { 9773 1.1 christos dns_name_t *name = NULL; 9774 1.1 christos dns_ttl_t ttl; 9775 1.1 christos isc_buffer_t *dbuf, b; 9776 1.1 christos 9777 1.1 christos /* 9778 1.9 christos * Determine the correct TTL to use for the SOA and RRSIG 9779 1.1 christos */ 9780 1.9 christos ttl = query_synthttl(*soardatasetp, *sigsoardatasetp, qctx->rdataset, 9781 1.9 christos qctx->sigrdataset, NULL, NULL); 9782 1.1 christos (*soardatasetp)->ttl = (*sigsoardatasetp)->ttl = ttl; 9783 1.1 christos 9784 1.1 christos /* 9785 1.1 christos * We want the SOA record to be first, so save the 9786 1.1 christos * NODATA proof's name now or else discard it. 9787 1.1 christos */ 9788 1.1 christos if (WANTDNSSEC(qctx->client)) { 9789 1.3 christos ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); 9790 1.1 christos } else { 9791 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 9792 1.1 christos } 9793 1.1 christos 9794 1.3 christos dbuf = ns_client_getnamebuf(qctx->client); 9795 1.3 christos name = ns_client_newname(qctx->client, dbuf, &b); 9796 1.20 christos dns_name_copy(signer, name); 9797 1.1 christos 9798 1.1 christos /* 9799 1.1 christos * Add SOA record. Omit the RRSIG if DNSSEC was not requested. 9800 1.1 christos */ 9801 1.1 christos if (!WANTDNSSEC(qctx->client)) { 9802 1.1 christos sigsoardatasetp = NULL; 9803 1.1 christos } 9804 1.9 christos query_addrrset(qctx, &name, soardatasetp, sigsoardatasetp, dbuf, 9805 1.9 christos DNS_SECTION_AUTHORITY); 9806 1.1 christos 9807 1.1 christos if (WANTDNSSEC(qctx->client)) { 9808 1.1 christos /* 9809 1.1 christos * Add NODATA proof. 9810 1.1 christos */ 9811 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, 9812 1.9 christos &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY); 9813 1.1 christos } 9814 1.1 christos 9815 1.1 christos inc_stats(qctx->client, ns_statscounter_nodatasynth); 9816 1.1 christos 9817 1.1 christos if (name != NULL) { 9818 1.3 christos ns_client_releasename(qctx->client, &name); 9819 1.1 christos } 9820 1.23 christos return ISC_R_SUCCESS; 9821 1.1 christos } 9822 1.1 christos 9823 1.1 christos /* 9824 1.1 christos * Synthesize a wildcard answer using the contents of 'rdataset'. 9825 1.1 christos * qctx contains the NODATA proof. 9826 1.1 christos */ 9827 1.1 christos static isc_result_t 9828 1.1 christos query_synthwildcard(query_ctx_t *qctx, dns_rdataset_t *rdataset, 9829 1.9 christos dns_rdataset_t *sigrdataset) { 9830 1.1 christos dns_name_t *name = NULL; 9831 1.1 christos isc_buffer_t *dbuf, b; 9832 1.3 christos dns_rdataset_t *cloneset = NULL, *clonesigset = NULL; 9833 1.1 christos dns_rdataset_t **sigrdatasetp; 9834 1.1 christos 9835 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_synthwildcard"); 9836 1.9 christos 9837 1.1 christos /* 9838 1.1 christos * We want the answer to be first, so save the 9839 1.1 christos * NOQNAME proof's name now or else discard it. 9840 1.1 christos */ 9841 1.1 christos if (WANTDNSSEC(qctx->client)) { 9842 1.3 christos ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); 9843 1.1 christos } else { 9844 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 9845 1.1 christos } 9846 1.1 christos 9847 1.3 christos dbuf = ns_client_getnamebuf(qctx->client); 9848 1.3 christos name = ns_client_newname(qctx->client, dbuf, &b); 9849 1.20 christos dns_name_copy(qctx->client->query.qname, name); 9850 1.1 christos 9851 1.3 christos cloneset = ns_client_newrdataset(qctx->client); 9852 1.3 christos dns_rdataset_clone(rdataset, cloneset); 9853 1.1 christos 9854 1.1 christos /* 9855 1.1 christos * Add answer RRset. Omit the RRSIG if DNSSEC was not requested. 9856 1.1 christos */ 9857 1.1 christos if (WANTDNSSEC(qctx->client)) { 9858 1.3 christos clonesigset = ns_client_newrdataset(qctx->client); 9859 1.3 christos dns_rdataset_clone(sigrdataset, clonesigset); 9860 1.3 christos sigrdatasetp = &clonesigset; 9861 1.1 christos } else { 9862 1.1 christos sigrdatasetp = NULL; 9863 1.1 christos } 9864 1.1 christos 9865 1.9 christos query_addrrset(qctx, &name, &cloneset, sigrdatasetp, dbuf, 9866 1.9 christos DNS_SECTION_ANSWER); 9867 1.1 christos 9868 1.1 christos if (WANTDNSSEC(qctx->client)) { 9869 1.1 christos /* 9870 1.1 christos * Add NOQNAME proof. 9871 1.1 christos */ 9872 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, 9873 1.9 christos &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY); 9874 1.1 christos } 9875 1.1 christos 9876 1.1 christos inc_stats(qctx->client, ns_statscounter_wildcardsynth); 9877 1.1 christos 9878 1.1 christos if (name != NULL) { 9879 1.3 christos ns_client_releasename(qctx->client, &name); 9880 1.1 christos } 9881 1.3 christos if (cloneset != NULL) { 9882 1.3 christos ns_client_putrdataset(qctx->client, &cloneset); 9883 1.1 christos } 9884 1.3 christos if (clonesigset != NULL) { 9885 1.3 christos ns_client_putrdataset(qctx->client, &clonesigset); 9886 1.1 christos } 9887 1.23 christos return ISC_R_SUCCESS; 9888 1.1 christos } 9889 1.1 christos 9890 1.1 christos /* 9891 1.1 christos * Add a synthesized CNAME record from the wildard RRset (rdataset) 9892 1.1 christos * and NODATA proof by calling query_synthwildcard then setup to 9893 1.1 christos * follow the CNAME. 9894 1.1 christos */ 9895 1.1 christos static isc_result_t 9896 1.1 christos query_synthcnamewildcard(query_ctx_t *qctx, dns_rdataset_t *rdataset, 9897 1.9 christos dns_rdataset_t *sigrdataset) { 9898 1.1 christos isc_result_t result; 9899 1.1 christos dns_name_t *tname = NULL; 9900 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 9901 1.1 christos dns_rdata_cname_t cname; 9902 1.1 christos 9903 1.1 christos result = query_synthwildcard(qctx, rdataset, sigrdataset); 9904 1.1 christos if (result != ISC_R_SUCCESS) { 9905 1.23 christos return result; 9906 1.1 christos } 9907 1.1 christos 9908 1.1 christos qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER; 9909 1.1 christos 9910 1.1 christos /* 9911 1.1 christos * Reset qname to be the target name of the CNAME and restart 9912 1.1 christos * the query. 9913 1.1 christos */ 9914 1.23 christos dns_message_gettempname(qctx->client->message, &tname); 9915 1.1 christos 9916 1.1 christos result = dns_rdataset_first(rdataset); 9917 1.1 christos if (result != ISC_R_SUCCESS) { 9918 1.1 christos dns_message_puttempname(qctx->client->message, &tname); 9919 1.23 christos return result; 9920 1.1 christos } 9921 1.1 christos 9922 1.1 christos dns_rdataset_current(rdataset, &rdata); 9923 1.1 christos result = dns_rdata_tostruct(&rdata, &cname, NULL); 9924 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 9925 1.1 christos dns_rdata_reset(&rdata); 9926 1.1 christos 9927 1.20 christos if (dns_name_equal(qctx->client->query.qname, &cname.cname)) { 9928 1.20 christos dns_message_puttempname(qctx->client->message, &tname); 9929 1.20 christos dns_rdata_freestruct(&cname); 9930 1.23 christos return ISC_R_SUCCESS; 9931 1.20 christos } 9932 1.20 christos 9933 1.20 christos dns_name_copy(&cname.cname, tname); 9934 1.1 christos 9935 1.1 christos dns_rdata_freestruct(&cname); 9936 1.1 christos ns_client_qnamereplace(qctx->client, tname); 9937 1.3 christos qctx->want_restart = true; 9938 1.1 christos if (!WANTRECURSION(qctx->client)) { 9939 1.23 christos qctx->options.nolog = true; 9940 1.1 christos } 9941 1.1 christos 9942 1.23 christos return result; 9943 1.1 christos } 9944 1.1 christos 9945 1.1 christos /* 9946 1.20 christos * Synthesize a NXDOMAIN or NODATA response from qctx (which contains the 9947 1.20 christos * NOQNAME proof), nowild + nowildrdataset + signowildrdataset (which 9948 1.20 christos * contains the NOWILDCARD proof or NODATA at wildcard) and 9949 1.20 christos * signer + soardatasetp + sigsoardatasetp which contain the 9950 1.20 christos * SOA record + RRSIG for the negative answer. 9951 1.1 christos */ 9952 1.1 christos static isc_result_t 9953 1.20 christos query_synthnxdomainnodata(query_ctx_t *qctx, bool nodata, dns_name_t *nowild, 9954 1.20 christos dns_rdataset_t *nowildrdataset, 9955 1.20 christos dns_rdataset_t *signowildrdataset, dns_name_t *signer, 9956 1.20 christos dns_rdataset_t **soardatasetp, 9957 1.20 christos dns_rdataset_t **sigsoardatasetp) { 9958 1.1 christos dns_name_t *name = NULL; 9959 1.1 christos dns_ttl_t ttl; 9960 1.1 christos isc_buffer_t *dbuf, b; 9961 1.3 christos dns_rdataset_t *cloneset = NULL, *clonesigset = NULL; 9962 1.1 christos 9963 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_synthnxdomain"); 9964 1.9 christos 9965 1.1 christos /* 9966 1.9 christos * Determine the correct TTL to use for the SOA and RRSIG 9967 1.1 christos */ 9968 1.9 christos ttl = query_synthttl(*soardatasetp, *sigsoardatasetp, qctx->rdataset, 9969 1.9 christos qctx->sigrdataset, nowildrdataset, 9970 1.9 christos signowildrdataset); 9971 1.1 christos (*soardatasetp)->ttl = (*sigsoardatasetp)->ttl = ttl; 9972 1.1 christos 9973 1.1 christos /* 9974 1.1 christos * We want the SOA record to be first, so save the 9975 1.1 christos * NOQNAME proof's name now or else discard it. 9976 1.1 christos */ 9977 1.1 christos if (WANTDNSSEC(qctx->client)) { 9978 1.3 christos ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); 9979 1.1 christos } else { 9980 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 9981 1.1 christos } 9982 1.1 christos 9983 1.3 christos dbuf = ns_client_getnamebuf(qctx->client); 9984 1.3 christos name = ns_client_newname(qctx->client, dbuf, &b); 9985 1.20 christos dns_name_copy(signer, name); 9986 1.1 christos 9987 1.1 christos /* 9988 1.1 christos * Add SOA record. Omit the RRSIG if DNSSEC was not requested. 9989 1.1 christos */ 9990 1.1 christos if (!WANTDNSSEC(qctx->client)) { 9991 1.1 christos sigsoardatasetp = NULL; 9992 1.1 christos } 9993 1.9 christos query_addrrset(qctx, &name, soardatasetp, sigsoardatasetp, dbuf, 9994 1.9 christos DNS_SECTION_AUTHORITY); 9995 1.1 christos 9996 1.1 christos if (WANTDNSSEC(qctx->client)) { 9997 1.1 christos /* 9998 1.1 christos * Add NOQNAME proof. 9999 1.1 christos */ 10000 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, 10001 1.9 christos &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY); 10002 1.1 christos 10003 1.3 christos dbuf = ns_client_getnamebuf(qctx->client); 10004 1.3 christos name = ns_client_newname(qctx->client, dbuf, &b); 10005 1.20 christos dns_name_copy(nowild, name); 10006 1.1 christos 10007 1.3 christos cloneset = ns_client_newrdataset(qctx->client); 10008 1.3 christos clonesigset = ns_client_newrdataset(qctx->client); 10009 1.1 christos 10010 1.3 christos dns_rdataset_clone(nowildrdataset, cloneset); 10011 1.3 christos dns_rdataset_clone(signowildrdataset, clonesigset); 10012 1.1 christos 10013 1.1 christos /* 10014 1.1 christos * Add NOWILDCARD proof. 10015 1.1 christos */ 10016 1.9 christos query_addrrset(qctx, &name, &cloneset, &clonesigset, dbuf, 10017 1.9 christos DNS_SECTION_AUTHORITY); 10018 1.1 christos } 10019 1.1 christos 10020 1.20 christos if (nodata) { 10021 1.20 christos inc_stats(qctx->client, ns_statscounter_nodatasynth); 10022 1.20 christos } else { 10023 1.20 christos qctx->client->message->rcode = dns_rcode_nxdomain; 10024 1.20 christos inc_stats(qctx->client, ns_statscounter_nxdomainsynth); 10025 1.20 christos } 10026 1.1 christos 10027 1.1 christos if (name != NULL) { 10028 1.3 christos ns_client_releasename(qctx->client, &name); 10029 1.1 christos } 10030 1.3 christos if (cloneset != NULL) { 10031 1.3 christos ns_client_putrdataset(qctx->client, &cloneset); 10032 1.1 christos } 10033 1.3 christos if (clonesigset != NULL) { 10034 1.3 christos ns_client_putrdataset(qctx->client, &clonesigset); 10035 1.1 christos } 10036 1.23 christos return ISC_R_SUCCESS; 10037 1.1 christos } 10038 1.1 christos 10039 1.1 christos /* 10040 1.1 christos * Check that all signer names in sigrdataset match the expected signer. 10041 1.1 christos */ 10042 1.1 christos static isc_result_t 10043 1.1 christos checksignames(dns_name_t *signer, dns_rdataset_t *sigrdataset) { 10044 1.1 christos isc_result_t result; 10045 1.1 christos 10046 1.9 christos for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS; 10047 1.9 christos result = dns_rdataset_next(sigrdataset)) 10048 1.9 christos { 10049 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 10050 1.1 christos dns_rdata_rrsig_t rrsig; 10051 1.1 christos 10052 1.1 christos dns_rdataset_current(sigrdataset, &rdata); 10053 1.1 christos result = dns_rdata_tostruct(&rdata, &rrsig, NULL); 10054 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 10055 1.1 christos if (dns_name_countlabels(signer) == 0) { 10056 1.20 christos dns_name_copy(&rrsig.signer, signer); 10057 1.1 christos } else if (!dns_name_equal(signer, &rrsig.signer)) { 10058 1.23 christos return ISC_R_FAILURE; 10059 1.1 christos } 10060 1.1 christos } 10061 1.1 christos 10062 1.23 christos return ISC_R_SUCCESS; 10063 1.1 christos } 10064 1.1 christos 10065 1.1 christos /*% 10066 1.1 christos * Handle covering NSEC responses. 10067 1.1 christos * 10068 1.9 christos * Verify the NSEC record is appropriate for the QNAME; if not, 10069 1.1 christos * redo the initial query without DNS_DBFIND_COVERINGNSEC. 10070 1.1 christos * 10071 1.1 christos * If the covering NSEC proves that the name exists but not the type, 10072 1.1 christos * synthesize a NODATA response. 10073 1.1 christos * 10074 1.1 christos * If the name doesn't exist, compute the wildcard record and check whether 10075 1.1 christos * the wildcard name exists or not. If we can't determine this, redo the 10076 1.1 christos * initial query without DNS_DBFIND_COVERINGNSEC. 10077 1.1 christos * 10078 1.1 christos * If the wildcard name does not exist, compute the SOA name and look that 10079 1.1 christos * up. If the SOA record does not exist, redo the initial query without 10080 1.1 christos * DNS_DBFIND_COVERINGNSEC. If the SOA record exists, synthesize an 10081 1.1 christos * NXDOMAIN response from the found records. 10082 1.1 christos * 10083 1.1 christos * If the wildcard name does exist, perform a lookup for the requested 10084 1.1 christos * type at the wildcard name. 10085 1.1 christos */ 10086 1.1 christos static isc_result_t 10087 1.1 christos query_coveringnsec(query_ctx_t *qctx) { 10088 1.1 christos dns_db_t *db = NULL; 10089 1.1 christos dns_clientinfo_t ci; 10090 1.1 christos dns_clientinfomethods_t cm; 10091 1.1 christos dns_dbnode_t *node = NULL; 10092 1.1 christos dns_fixedname_t fixed; 10093 1.20 christos dns_fixedname_t fnamespace; 10094 1.1 christos dns_fixedname_t fnowild; 10095 1.1 christos dns_fixedname_t fsigner; 10096 1.1 christos dns_fixedname_t fwild; 10097 1.1 christos dns_name_t *fname = NULL; 10098 1.20 christos dns_name_t *namespace = NULL; 10099 1.1 christos dns_name_t *nowild = NULL; 10100 1.1 christos dns_name_t *signer = NULL; 10101 1.1 christos dns_name_t *wild = NULL; 10102 1.20 christos dns_name_t qname; 10103 1.1 christos dns_rdataset_t *soardataset = NULL, *sigsoardataset = NULL; 10104 1.1 christos dns_rdataset_t rdataset, sigrdataset; 10105 1.3 christos bool done = false; 10106 1.3 christos bool exists = true, data = true; 10107 1.3 christos bool redirected = false; 10108 1.1 christos isc_result_t result = ISC_R_SUCCESS; 10109 1.1 christos unsigned int dboptions = qctx->client->query.dboptions; 10110 1.20 christos unsigned int labels; 10111 1.1 christos 10112 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_coveringnsec"); 10113 1.9 christos 10114 1.20 christos dns_name_init(&qname, NULL); 10115 1.1 christos dns_rdataset_init(&rdataset); 10116 1.1 christos dns_rdataset_init(&sigrdataset); 10117 1.20 christos namespace = dns_fixedname_initname(&fnamespace); 10118 1.20 christos 10119 1.20 christos /* 10120 1.20 christos * Check that the NSEC record is from the correct namespace. 10121 1.20 christos * For records that belong to the parent zone (i.e. DS), 10122 1.20 christos * remove a label to find the correct namespace. 10123 1.20 christos */ 10124 1.20 christos dns_name_clone(qctx->client->query.qname, &qname); 10125 1.20 christos labels = dns_name_countlabels(&qname); 10126 1.20 christos if (dns_rdatatype_atparent(qctx->qtype) && labels > 1) { 10127 1.20 christos dns_name_getlabelsequence(&qname, 1, labels - 1, &qname); 10128 1.20 christos } 10129 1.20 christos dns_view_sfd_find(qctx->view, &qname, namespace); 10130 1.20 christos if (!dns_name_issubdomain(qctx->fname, namespace)) { 10131 1.20 christos goto cleanup; 10132 1.20 christos } 10133 1.1 christos 10134 1.1 christos /* 10135 1.1 christos * If we have no signer name, stop immediately. 10136 1.1 christos */ 10137 1.1 christos if (!dns_rdataset_isassociated(qctx->sigrdataset)) { 10138 1.1 christos goto cleanup; 10139 1.1 christos } 10140 1.1 christos 10141 1.1 christos wild = dns_fixedname_initname(&fwild); 10142 1.1 christos fname = dns_fixedname_initname(&fixed); 10143 1.1 christos signer = dns_fixedname_initname(&fsigner); 10144 1.1 christos nowild = dns_fixedname_initname(&fnowild); 10145 1.1 christos 10146 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 10147 1.20 christos dns_clientinfo_init(&ci, qctx->client, NULL); 10148 1.1 christos 10149 1.1 christos /* 10150 1.1 christos * All signer names must be the same to accept. 10151 1.1 christos */ 10152 1.1 christos result = checksignames(signer, qctx->sigrdataset); 10153 1.1 christos if (result != ISC_R_SUCCESS) { 10154 1.1 christos result = ISC_R_SUCCESS; 10155 1.1 christos goto cleanup; 10156 1.1 christos } 10157 1.1 christos 10158 1.1 christos /* 10159 1.20 christos * If NSEC or RRSIG are missing from the type map 10160 1.20 christos * reject the NSEC RRset. 10161 1.20 christos */ 10162 1.20 christos if (!dns_nsec_requiredtypespresent(qctx->rdataset)) { 10163 1.20 christos goto cleanup; 10164 1.20 christos } 10165 1.20 christos 10166 1.20 christos /* 10167 1.1 christos * Check that we have the correct NOQNAME NSEC record. 10168 1.1 christos */ 10169 1.1 christos result = dns_nsec_noexistnodata(qctx->qtype, qctx->client->query.qname, 10170 1.9 christos qctx->fname, qctx->rdataset, &exists, 10171 1.9 christos &data, wild, log_noexistnodata, qctx); 10172 1.1 christos 10173 1.1 christos if (result != ISC_R_SUCCESS || (exists && data)) { 10174 1.1 christos goto cleanup; 10175 1.1 christos } 10176 1.1 christos 10177 1.1 christos if (exists) { 10178 1.9 christos if (qctx->type == dns_rdatatype_any) { /* XXX not yet */ 10179 1.1 christos goto cleanup; 10180 1.1 christos } 10181 1.3 christos if (!ISC_LIST_EMPTY(qctx->view->dns64) && 10182 1.1 christos (qctx->type == dns_rdatatype_a || 10183 1.1 christos qctx->type == dns_rdatatype_aaaa)) /* XXX not yet */ 10184 1.1 christos { 10185 1.1 christos goto cleanup; 10186 1.1 christos } 10187 1.1 christos if (!qctx->resuming && !STALE(qctx->rdataset) && 10188 1.1 christos qctx->rdataset->ttl == 0 && RECURSIONOK(qctx->client)) 10189 1.1 christos { 10190 1.1 christos goto cleanup; 10191 1.1 christos } 10192 1.1 christos 10193 1.3 christos soardataset = ns_client_newrdataset(qctx->client); 10194 1.3 christos sigsoardataset = ns_client_newrdataset(qctx->client); 10195 1.1 christos 10196 1.1 christos /* 10197 1.1 christos * Look for SOA record to construct NODATA response. 10198 1.1 christos */ 10199 1.1 christos dns_db_attach(qctx->db, &db); 10200 1.1 christos result = dns_db_findext(db, signer, qctx->version, 10201 1.1 christos dns_rdatatype_soa, dboptions, 10202 1.9 christos qctx->client->now, &node, fname, &cm, 10203 1.9 christos &ci, soardataset, sigsoardataset); 10204 1.1 christos 10205 1.1 christos if (result != ISC_R_SUCCESS) { 10206 1.1 christos goto cleanup; 10207 1.1 christos } 10208 1.9 christos (void)query_synthnodata(qctx, signer, &soardataset, 10209 1.9 christos &sigsoardataset); 10210 1.3 christos done = true; 10211 1.1 christos goto cleanup; 10212 1.1 christos } 10213 1.1 christos 10214 1.1 christos /* 10215 1.1 christos * Look up the no-wildcard proof. 10216 1.1 christos */ 10217 1.1 christos dns_db_attach(qctx->db, &db); 10218 1.1 christos result = dns_db_findext(db, wild, qctx->version, qctx->type, 10219 1.1 christos dboptions | DNS_DBFIND_COVERINGNSEC, 10220 1.9 christos qctx->client->now, &node, nowild, &cm, &ci, 10221 1.9 christos &rdataset, &sigrdataset); 10222 1.1 christos 10223 1.1 christos if (rdataset.trust != dns_trust_secure || 10224 1.16 christos sigrdataset.trust != dns_trust_secure) 10225 1.16 christos { 10226 1.1 christos goto cleanup; 10227 1.1 christos } 10228 1.1 christos 10229 1.1 christos /* 10230 1.1 christos * Zero TTL handling of wildcard record. 10231 1.1 christos * 10232 1.3 christos * We don't yet have code to handle synthesis and type ANY or dns64 10233 1.3 christos * processing so we abort the synthesis here if there would be a 10234 1.3 christos * interaction. 10235 1.1 christos */ 10236 1.1 christos switch (result) { 10237 1.1 christos case ISC_R_SUCCESS: 10238 1.9 christos if (qctx->type == dns_rdatatype_any) { /* XXX not yet */ 10239 1.1 christos goto cleanup; 10240 1.1 christos } 10241 1.3 christos if (!ISC_LIST_EMPTY(qctx->view->dns64) && 10242 1.1 christos (qctx->type == dns_rdatatype_a || 10243 1.1 christos qctx->type == dns_rdatatype_aaaa)) /* XXX not yet */ 10244 1.1 christos { 10245 1.1 christos goto cleanup; 10246 1.1 christos } 10247 1.15 christos FALLTHROUGH; 10248 1.1 christos case DNS_R_CNAME: 10249 1.9 christos if (!qctx->resuming && !STALE(&rdataset) && rdataset.ttl == 0 && 10250 1.9 christos RECURSIONOK(qctx->client)) 10251 1.1 christos { 10252 1.1 christos goto cleanup; 10253 1.1 christos } 10254 1.1 christos default: 10255 1.1 christos break; 10256 1.1 christos } 10257 1.1 christos 10258 1.1 christos switch (result) { 10259 1.1 christos case DNS_R_COVERINGNSEC: 10260 1.20 christos /* 10261 1.20 christos * Check that the covering NSEC record is from the right 10262 1.20 christos * namespace. 10263 1.20 christos */ 10264 1.20 christos if (!dns_name_issubdomain(nowild, namespace)) { 10265 1.20 christos goto cleanup; 10266 1.20 christos } 10267 1.9 christos result = dns_nsec_noexistnodata(qctx->qtype, wild, nowild, 10268 1.9 christos &rdataset, &exists, &data, NULL, 10269 1.1 christos log_noexistnodata, qctx); 10270 1.20 christos if (result != ISC_R_SUCCESS || (exists && data)) { 10271 1.1 christos goto cleanup; 10272 1.1 christos } 10273 1.1 christos break; 10274 1.9 christos case ISC_R_SUCCESS: /* wild card match */ 10275 1.1 christos (void)query_synthwildcard(qctx, &rdataset, &sigrdataset); 10276 1.3 christos done = true; 10277 1.1 christos goto cleanup; 10278 1.9 christos case DNS_R_CNAME: /* wild card cname */ 10279 1.1 christos (void)query_synthcnamewildcard(qctx, &rdataset, &sigrdataset); 10280 1.3 christos done = true; 10281 1.1 christos goto cleanup; 10282 1.9 christos case DNS_R_NCACHENXRRSET: /* wild card nodata */ 10283 1.9 christos case DNS_R_NCACHENXDOMAIN: /* direct nxdomain */ 10284 1.1 christos default: 10285 1.1 christos goto cleanup; 10286 1.1 christos } 10287 1.1 christos 10288 1.1 christos /* 10289 1.1 christos * We now have the proof that we have an NXDOMAIN. Apply 10290 1.1 christos * NXDOMAIN redirection if configured. 10291 1.1 christos */ 10292 1.18 christos result = query_redirect(qctx, DNS_R_COVERINGNSEC); 10293 1.1 christos if (result != ISC_R_COMPLETE) { 10294 1.3 christos redirected = true; 10295 1.1 christos goto cleanup; 10296 1.1 christos } 10297 1.1 christos 10298 1.1 christos /* 10299 1.1 christos * Must be signed to accept. 10300 1.1 christos */ 10301 1.1 christos if (!dns_rdataset_isassociated(&sigrdataset)) { 10302 1.1 christos goto cleanup; 10303 1.1 christos } 10304 1.1 christos 10305 1.1 christos /* 10306 1.1 christos * Check signer signer names again. 10307 1.1 christos */ 10308 1.1 christos result = checksignames(signer, &sigrdataset); 10309 1.1 christos if (result != ISC_R_SUCCESS) { 10310 1.1 christos result = ISC_R_SUCCESS; 10311 1.1 christos goto cleanup; 10312 1.1 christos } 10313 1.1 christos 10314 1.1 christos if (node != NULL) { 10315 1.1 christos dns_db_detachnode(db, &node); 10316 1.1 christos } 10317 1.1 christos 10318 1.3 christos soardataset = ns_client_newrdataset(qctx->client); 10319 1.3 christos sigsoardataset = ns_client_newrdataset(qctx->client); 10320 1.1 christos 10321 1.1 christos /* 10322 1.1 christos * Look for SOA record to construct NXDOMAIN response. 10323 1.1 christos */ 10324 1.9 christos result = dns_db_findext(db, signer, qctx->version, dns_rdatatype_soa, 10325 1.9 christos dboptions, qctx->client->now, &node, fname, &cm, 10326 1.9 christos &ci, soardataset, sigsoardataset); 10327 1.1 christos 10328 1.1 christos if (result != ISC_R_SUCCESS) { 10329 1.1 christos goto cleanup; 10330 1.1 christos } 10331 1.20 christos (void)query_synthnxdomainnodata(qctx, exists, nowild, &rdataset, 10332 1.20 christos &sigrdataset, signer, &soardataset, 10333 1.20 christos &sigsoardataset); 10334 1.3 christos done = true; 10335 1.1 christos 10336 1.9 christos cleanup: 10337 1.1 christos if (dns_rdataset_isassociated(&rdataset)) { 10338 1.1 christos dns_rdataset_disassociate(&rdataset); 10339 1.1 christos } 10340 1.1 christos if (dns_rdataset_isassociated(&sigrdataset)) { 10341 1.1 christos dns_rdataset_disassociate(&sigrdataset); 10342 1.1 christos } 10343 1.1 christos if (soardataset != NULL) { 10344 1.3 christos ns_client_putrdataset(qctx->client, &soardataset); 10345 1.1 christos } 10346 1.1 christos if (sigsoardataset != NULL) { 10347 1.3 christos ns_client_putrdataset(qctx->client, &sigsoardataset); 10348 1.1 christos } 10349 1.1 christos if (db != NULL) { 10350 1.1 christos if (node != NULL) { 10351 1.1 christos dns_db_detachnode(db, &node); 10352 1.1 christos } 10353 1.1 christos dns_db_detach(&db); 10354 1.1 christos } 10355 1.1 christos 10356 1.1 christos if (redirected) { 10357 1.23 christos return result; 10358 1.1 christos } 10359 1.1 christos 10360 1.1 christos if (!done) { 10361 1.1 christos /* 10362 1.1 christos * No covering NSEC was found; proceed with recursion. 10363 1.1 christos */ 10364 1.3 christos qctx->findcoveringnsec = false; 10365 1.1 christos if (qctx->fname != NULL) { 10366 1.3 christos ns_client_releasename(qctx->client, &qctx->fname); 10367 1.1 christos } 10368 1.1 christos if (qctx->node != NULL) { 10369 1.1 christos dns_db_detachnode(qctx->db, &qctx->node); 10370 1.1 christos } 10371 1.3 christos ns_client_putrdataset(qctx->client, &qctx->rdataset); 10372 1.1 christos if (qctx->sigrdataset != NULL) { 10373 1.3 christos ns_client_putrdataset(qctx->client, &qctx->sigrdataset); 10374 1.1 christos } 10375 1.23 christos return query_lookup(qctx); 10376 1.1 christos } 10377 1.1 christos 10378 1.23 christos return ns_query_done(qctx); 10379 1.1 christos } 10380 1.1 christos 10381 1.1 christos /*% 10382 1.1 christos * Handle negative cache responses, DNS_R_NCACHENXRRSET or 10383 1.1 christos * DNS_R_NCACHENXDOMAIN. (Note: may also be called with result 10384 1.1 christos * set to DNS_R_NXDOMAIN when handling DNS64 lookups.) 10385 1.1 christos */ 10386 1.1 christos static isc_result_t 10387 1.1 christos query_ncache(query_ctx_t *qctx, isc_result_t result) { 10388 1.1 christos INSIST(!qctx->is_zone); 10389 1.1 christos INSIST(result == DNS_R_NCACHENXDOMAIN || 10390 1.9 christos result == DNS_R_NCACHENXRRSET || result == DNS_R_NXDOMAIN); 10391 1.9 christos 10392 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_ncache"); 10393 1.1 christos 10394 1.3 christos CALL_HOOK(NS_QUERY_NCACHE_BEGIN, qctx); 10395 1.3 christos 10396 1.3 christos qctx->authoritative = false; 10397 1.1 christos 10398 1.1 christos if (result == DNS_R_NCACHENXDOMAIN) { 10399 1.1 christos /* 10400 1.1 christos * Set message rcode. (This is not done when 10401 1.1 christos * result == DNS_R_NXDOMAIN because that means we're 10402 1.1 christos * being called after a DNS64 lookup and don't want 10403 1.1 christos * to update the rcode now.) 10404 1.1 christos */ 10405 1.1 christos qctx->client->message->rcode = dns_rcode_nxdomain; 10406 1.1 christos 10407 1.1 christos /* Look for RFC 1918 leakage from Internet. */ 10408 1.1 christos if (qctx->qtype == dns_rdatatype_ptr && 10409 1.1 christos qctx->client->message->rdclass == dns_rdataclass_in && 10410 1.1 christos dns_name_countlabels(qctx->fname) == 7) 10411 1.1 christos { 10412 1.1 christos warn_rfc1918(qctx->client, qctx->fname, qctx->rdataset); 10413 1.1 christos } 10414 1.1 christos } 10415 1.1 christos 10416 1.26 christos if (!qctx->is_zone && RECURSIONOK(qctx->client)) { 10417 1.26 christos query_stale_refresh_ncache(qctx->client); 10418 1.26 christos } 10419 1.26 christos 10420 1.23 christos return query_nodata(qctx, result); 10421 1.3 christos 10422 1.9 christos cleanup: 10423 1.23 christos return result; 10424 1.3 christos } 10425 1.3 christos 10426 1.3 christos /* 10427 1.3 christos * If we have a zero ttl from the cache, refetch. 10428 1.3 christos */ 10429 1.3 christos static isc_result_t 10430 1.3 christos query_zerottl_refetch(query_ctx_t *qctx) { 10431 1.3 christos isc_result_t result; 10432 1.3 christos 10433 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_zerottl_refetch"); 10434 1.9 christos 10435 1.3 christos if (qctx->is_zone || qctx->resuming || STALE(qctx->rdataset) || 10436 1.3 christos qctx->rdataset->ttl != 0 || !RECURSIONOK(qctx->client)) 10437 1.3 christos { 10438 1.23 christos return ISC_R_COMPLETE; 10439 1.3 christos } 10440 1.3 christos 10441 1.3 christos qctx_clean(qctx); 10442 1.3 christos 10443 1.3 christos INSIST(!REDIRECT(qctx->client)); 10444 1.3 christos 10445 1.3 christos result = ns_query_recurse(qctx->client, qctx->qtype, 10446 1.9 christos qctx->client->query.qname, NULL, NULL, 10447 1.9 christos qctx->resuming); 10448 1.3 christos if (result == ISC_R_SUCCESS) { 10449 1.3 christos CALL_HOOK(NS_QUERY_ZEROTTL_RECURSE, qctx); 10450 1.9 christos qctx->client->query.attributes |= NS_QUERYATTR_RECURSING; 10451 1.3 christos 10452 1.3 christos if (qctx->dns64) { 10453 1.9 christos qctx->client->query.attributes |= NS_QUERYATTR_DNS64; 10454 1.3 christos } 10455 1.3 christos if (qctx->dns64_exclude) { 10456 1.3 christos qctx->client->query.attributes |= 10457 1.3 christos NS_QUERYATTR_DNS64EXCLUDE; 10458 1.3 christos } 10459 1.3 christos } else { 10460 1.13 christos /* 10461 1.13 christos * There was a zero ttl from the cache, don't fallback to 10462 1.13 christos * serve-stale lookup. 10463 1.13 christos */ 10464 1.3 christos QUERY_ERROR(qctx, result); 10465 1.3 christos } 10466 1.3 christos 10467 1.23 christos return ns_query_done(qctx); 10468 1.3 christos 10469 1.9 christos cleanup: 10470 1.23 christos return result; 10471 1.1 christos } 10472 1.1 christos 10473 1.1 christos /* 10474 1.1 christos * Handle CNAME responses. 10475 1.1 christos */ 10476 1.1 christos static isc_result_t 10477 1.1 christos query_cname(query_ctx_t *qctx) { 10478 1.14 christos isc_result_t result = ISC_R_UNSET; 10479 1.14 christos dns_name_t *tname = NULL; 10480 1.14 christos dns_rdataset_t *trdataset = NULL; 10481 1.1 christos dns_rdataset_t **sigrdatasetp = NULL; 10482 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 10483 1.1 christos dns_rdata_cname_t cname; 10484 1.1 christos 10485 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_cname"); 10486 1.9 christos 10487 1.3 christos CALL_HOOK(NS_QUERY_CNAME_BEGIN, qctx); 10488 1.1 christos 10489 1.3 christos result = query_zerottl_refetch(qctx); 10490 1.3 christos if (result != ISC_R_COMPLETE) { 10491 1.23 christos goto cleanup; 10492 1.1 christos } 10493 1.1 christos 10494 1.1 christos /* 10495 1.1 christos * Keep a copy of the rdataset. We have to do this because 10496 1.1 christos * query_addrrset may clear 'rdataset' (to prevent the 10497 1.1 christos * cleanup code from cleaning it up). 10498 1.1 christos */ 10499 1.1 christos trdataset = qctx->rdataset; 10500 1.1 christos 10501 1.1 christos /* 10502 1.1 christos * Add the CNAME to the answer section. 10503 1.1 christos */ 10504 1.9 christos if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) { 10505 1.1 christos sigrdatasetp = &qctx->sigrdataset; 10506 1.9 christos } 10507 1.1 christos 10508 1.23 christos if (WANTDNSSEC(qctx->client) && qctx->fname->attributes.wildcard) { 10509 1.1 christos dns_fixedname_init(&qctx->wildcardname); 10510 1.20 christos dns_name_copy(qctx->fname, 10511 1.20 christos dns_fixedname_name(&qctx->wildcardname)); 10512 1.3 christos qctx->need_wildcardproof = true; 10513 1.1 christos } 10514 1.1 christos 10515 1.1 christos if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client)) { 10516 1.1 christos qctx->noqname = qctx->rdataset; 10517 1.1 christos } else { 10518 1.1 christos qctx->noqname = NULL; 10519 1.1 christos } 10520 1.1 christos 10521 1.9 christos if (!qctx->is_zone && RECURSIONOK(qctx->client)) { 10522 1.1 christos query_prefetch(qctx->client, qctx->fname, qctx->rdataset); 10523 1.9 christos } 10524 1.1 christos 10525 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp, 10526 1.9 christos qctx->dbuf, DNS_SECTION_ANSWER); 10527 1.1 christos 10528 1.1 christos query_addnoqnameproof(qctx); 10529 1.1 christos 10530 1.1 christos /* 10531 1.1 christos * We set the PARTIALANSWER attribute so that if anything goes 10532 1.1 christos * wrong later on, we'll return what we've got so far. 10533 1.1 christos */ 10534 1.1 christos qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER; 10535 1.1 christos 10536 1.1 christos /* 10537 1.1 christos * Reset qname to be the target name of the CNAME and restart 10538 1.1 christos * the query. 10539 1.1 christos */ 10540 1.23 christos dns_message_gettempname(qctx->client->message, &tname); 10541 1.1 christos 10542 1.1 christos result = dns_rdataset_first(trdataset); 10543 1.1 christos if (result != ISC_R_SUCCESS) { 10544 1.1 christos dns_message_puttempname(qctx->client->message, &tname); 10545 1.23 christos (void)ns_query_done(qctx); 10546 1.23 christos goto cleanup; 10547 1.1 christos } 10548 1.1 christos 10549 1.1 christos dns_rdataset_current(trdataset, &rdata); 10550 1.1 christos result = dns_rdata_tostruct(&rdata, &cname, NULL); 10551 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 10552 1.1 christos dns_rdata_reset(&rdata); 10553 1.1 christos 10554 1.20 christos dns_name_copy(&cname.cname, tname); 10555 1.1 christos 10556 1.1 christos dns_rdata_freestruct(&cname); 10557 1.1 christos ns_client_qnamereplace(qctx->client, tname); 10558 1.3 christos qctx->want_restart = true; 10559 1.9 christos if (!WANTRECURSION(qctx->client)) { 10560 1.23 christos qctx->options.nolog = true; 10561 1.9 christos } 10562 1.1 christos 10563 1.1 christos query_addauth(qctx); 10564 1.1 christos 10565 1.23 christos return ns_query_done(qctx); 10566 1.3 christos 10567 1.9 christos cleanup: 10568 1.23 christos return result; 10569 1.1 christos } 10570 1.1 christos 10571 1.1 christos /* 10572 1.1 christos * Handle DNAME responses. 10573 1.1 christos */ 10574 1.1 christos static isc_result_t 10575 1.1 christos query_dname(query_ctx_t *qctx) { 10576 1.1 christos dns_name_t *tname, *prefix; 10577 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 10578 1.1 christos dns_rdata_dname_t dname; 10579 1.1 christos dns_fixedname_t fixed; 10580 1.1 christos dns_rdataset_t *trdataset; 10581 1.1 christos dns_rdataset_t **sigrdatasetp = NULL; 10582 1.1 christos dns_namereln_t namereln; 10583 1.1 christos isc_buffer_t b; 10584 1.1 christos int order; 10585 1.20 christos isc_result_t result = ISC_R_UNSET; 10586 1.1 christos unsigned int nlabels; 10587 1.1 christos 10588 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_dname"); 10589 1.9 christos 10590 1.3 christos CALL_HOOK(NS_QUERY_DNAME_BEGIN, qctx); 10591 1.3 christos 10592 1.1 christos /* 10593 1.1 christos * Compare the current qname to the found name. We need 10594 1.1 christos * to know how many labels and bits are in common because 10595 1.1 christos * we're going to have to split qname later on. 10596 1.1 christos */ 10597 1.1 christos namereln = dns_name_fullcompare(qctx->client->query.qname, qctx->fname, 10598 1.1 christos &order, &nlabels); 10599 1.1 christos INSIST(namereln == dns_namereln_subdomain); 10600 1.1 christos 10601 1.1 christos /* 10602 1.1 christos * Keep a copy of the rdataset. We have to do this because 10603 1.1 christos * query_addrrset may clear 'rdataset' (to prevent the 10604 1.1 christos * cleanup code from cleaning it up). 10605 1.1 christos */ 10606 1.1 christos trdataset = qctx->rdataset; 10607 1.1 christos 10608 1.1 christos /* 10609 1.1 christos * Add the DNAME to the answer section. 10610 1.1 christos */ 10611 1.9 christos if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) { 10612 1.1 christos sigrdatasetp = &qctx->sigrdataset; 10613 1.9 christos } 10614 1.1 christos 10615 1.23 christos if (WANTDNSSEC(qctx->client) && qctx->fname->attributes.wildcard) { 10616 1.1 christos dns_fixedname_init(&qctx->wildcardname); 10617 1.20 christos dns_name_copy(qctx->fname, 10618 1.20 christos dns_fixedname_name(&qctx->wildcardname)); 10619 1.3 christos qctx->need_wildcardproof = true; 10620 1.1 christos } 10621 1.1 christos 10622 1.9 christos if (!qctx->is_zone && RECURSIONOK(qctx->client)) { 10623 1.1 christos query_prefetch(qctx->client, qctx->fname, qctx->rdataset); 10624 1.9 christos } 10625 1.9 christos query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp, 10626 1.9 christos qctx->dbuf, DNS_SECTION_ANSWER); 10627 1.1 christos 10628 1.1 christos /* 10629 1.1 christos * We set the PARTIALANSWER attribute so that if anything goes 10630 1.1 christos * wrong later on, we'll return what we've got so far. 10631 1.1 christos */ 10632 1.1 christos qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER; 10633 1.1 christos 10634 1.1 christos /* 10635 1.1 christos * Get the target name of the DNAME. 10636 1.1 christos */ 10637 1.1 christos tname = NULL; 10638 1.23 christos dns_message_gettempname(qctx->client->message, &tname); 10639 1.1 christos 10640 1.1 christos result = dns_rdataset_first(trdataset); 10641 1.1 christos if (result != ISC_R_SUCCESS) { 10642 1.1 christos dns_message_puttempname(qctx->client->message, &tname); 10643 1.23 christos (void)ns_query_done(qctx); 10644 1.23 christos goto cleanup; 10645 1.1 christos } 10646 1.1 christos 10647 1.1 christos dns_rdataset_current(trdataset, &rdata); 10648 1.1 christos result = dns_rdata_tostruct(&rdata, &dname, NULL); 10649 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 10650 1.1 christos dns_rdata_reset(&rdata); 10651 1.1 christos 10652 1.20 christos dns_name_copy(&dname.dname, tname); 10653 1.1 christos dns_rdata_freestruct(&dname); 10654 1.1 christos 10655 1.1 christos /* 10656 1.1 christos * Construct the new qname consisting of 10657 1.1 christos * <found name prefix>.<dname target> 10658 1.1 christos */ 10659 1.1 christos prefix = dns_fixedname_initname(&fixed); 10660 1.1 christos dns_name_split(qctx->client->query.qname, nlabels, prefix, NULL); 10661 1.1 christos INSIST(qctx->fname == NULL); 10662 1.3 christos qctx->dbuf = ns_client_getnamebuf(qctx->client); 10663 1.3 christos qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b); 10664 1.1 christos result = dns_name_concatenate(prefix, tname, qctx->fname, NULL); 10665 1.1 christos dns_message_puttempname(qctx->client->message, &tname); 10666 1.1 christos 10667 1.1 christos /* 10668 1.1 christos * RFC2672, section 4.1, subsection 3c says 10669 1.1 christos * we should return YXDOMAIN if the constructed 10670 1.1 christos * name would be too long. 10671 1.1 christos */ 10672 1.9 christos if (result == DNS_R_NAMETOOLONG) { 10673 1.1 christos qctx->client->message->rcode = dns_rcode_yxdomain; 10674 1.9 christos } 10675 1.9 christos if (result != ISC_R_SUCCESS) { 10676 1.23 christos (void)ns_query_done(qctx); 10677 1.23 christos goto cleanup; 10678 1.9 christos } 10679 1.1 christos 10680 1.3 christos ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); 10681 1.1 christos 10682 1.1 christos /* 10683 1.1 christos * Synthesize a CNAME consisting of 10684 1.1 christos * <old qname> <dname ttl> CNAME <new qname> 10685 1.1 christos * with <dname trust value> 10686 1.1 christos * 10687 1.1 christos * Synthesize a CNAME so old old clients that don't understand 10688 1.1 christos * DNAME can chain. 10689 1.1 christos * 10690 1.1 christos * We do not try to synthesize a signature because we hope 10691 1.1 christos * that security aware servers will understand DNAME. Also, 10692 1.1 christos * even if we had an online key, making a signature 10693 1.1 christos * on-the-fly is costly, and not really legitimate anyway 10694 1.1 christos * since the synthesized CNAME is NOT in the zone. 10695 1.1 christos */ 10696 1.23 christos query_addcname(qctx, trdataset->trust, trdataset->ttl); 10697 1.1 christos 10698 1.1 christos /* 10699 1.11 christos * If the original query was not for a CNAME or ANY then follow the 10700 1.11 christos * CNAME. 10701 1.1 christos */ 10702 1.11 christos if (qctx->qtype != dns_rdatatype_cname && 10703 1.16 christos qctx->qtype != dns_rdatatype_any) 10704 1.16 christos { 10705 1.11 christos /* 10706 1.11 christos * Switch to the new qname and restart. 10707 1.11 christos */ 10708 1.11 christos ns_client_qnamereplace(qctx->client, qctx->fname); 10709 1.11 christos qctx->fname = NULL; 10710 1.11 christos qctx->want_restart = true; 10711 1.11 christos if (!WANTRECURSION(qctx->client)) { 10712 1.23 christos qctx->options.nolog = true; 10713 1.11 christos } 10714 1.9 christos } 10715 1.1 christos 10716 1.1 christos query_addauth(qctx); 10717 1.1 christos 10718 1.23 christos return ns_query_done(qctx); 10719 1.3 christos 10720 1.9 christos cleanup: 10721 1.23 christos return result; 10722 1.1 christos } 10723 1.1 christos 10724 1.1 christos /*% 10725 1.9 christos * Add CNAME to response. 10726 1.1 christos */ 10727 1.23 christos static void 10728 1.1 christos query_addcname(query_ctx_t *qctx, dns_trust_t trust, dns_ttl_t ttl) { 10729 1.1 christos ns_client_t *client = qctx->client; 10730 1.1 christos dns_rdataset_t *rdataset = NULL; 10731 1.1 christos dns_rdatalist_t *rdatalist = NULL; 10732 1.1 christos dns_rdata_t *rdata = NULL; 10733 1.1 christos isc_region_t r; 10734 1.1 christos dns_name_t *aname = NULL; 10735 1.1 christos 10736 1.23 christos dns_message_gettempname(client->message, &aname); 10737 1.14 christos 10738 1.20 christos dns_name_copy(client->query.qname, aname); 10739 1.1 christos 10740 1.23 christos dns_message_gettemprdatalist(client->message, &rdatalist); 10741 1.1 christos 10742 1.23 christos dns_message_gettemprdata(client->message, &rdata); 10743 1.1 christos 10744 1.23 christos dns_message_gettemprdataset(client->message, &rdataset); 10745 1.1 christos 10746 1.1 christos rdatalist->type = dns_rdatatype_cname; 10747 1.1 christos rdatalist->rdclass = client->message->rdclass; 10748 1.1 christos rdatalist->ttl = ttl; 10749 1.1 christos 10750 1.1 christos dns_name_toregion(qctx->fname, &r); 10751 1.1 christos rdata->data = r.base; 10752 1.1 christos rdata->length = r.length; 10753 1.1 christos rdata->rdclass = client->message->rdclass; 10754 1.1 christos rdata->type = dns_rdatatype_cname; 10755 1.1 christos 10756 1.1 christos ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 10757 1.23 christos dns_rdatalist_tordataset(rdatalist, rdataset); 10758 1.1 christos rdataset->trust = trust; 10759 1.1 christos dns_rdataset_setownercase(rdataset, aname); 10760 1.1 christos 10761 1.9 christos query_addrrset(qctx, &aname, &rdataset, NULL, NULL, DNS_SECTION_ANSWER); 10762 1.1 christos if (rdataset != NULL) { 10763 1.9 christos if (dns_rdataset_isassociated(rdataset)) { 10764 1.1 christos dns_rdataset_disassociate(rdataset); 10765 1.9 christos } 10766 1.1 christos dns_message_puttemprdataset(client->message, &rdataset); 10767 1.1 christos } 10768 1.9 christos if (aname != NULL) { 10769 1.1 christos dns_message_puttempname(client->message, &aname); 10770 1.9 christos } 10771 1.1 christos } 10772 1.1 christos 10773 1.1 christos /*% 10774 1.1 christos * Prepare to respond: determine whether a wildcard proof is needed, 10775 1.3 christos * then hand off to query_respond() or (for type ANY queries) 10776 1.3 christos * query_respond_any(). 10777 1.1 christos */ 10778 1.1 christos static isc_result_t 10779 1.1 christos query_prepresponse(query_ctx_t *qctx) { 10780 1.20 christos isc_result_t result = ISC_R_UNSET; 10781 1.3 christos 10782 1.9 christos CCTRACE(ISC_LOG_DEBUG(3), "query_prepresponse"); 10783 1.9 christos 10784 1.3 christos CALL_HOOK(NS_QUERY_PREP_RESPONSE_BEGIN, qctx); 10785 1.3 christos 10786 1.23 christos if (WANTDNSSEC(qctx->client) && qctx->fname->attributes.wildcard) { 10787 1.1 christos dns_fixedname_init(&qctx->wildcardname); 10788 1.20 christos dns_name_copy(qctx->fname, 10789 1.20 christos dns_fixedname_name(&qctx->wildcardname)); 10790 1.3 christos qctx->need_wildcardproof = true; 10791 1.3 christos } 10792 1.3 christos 10793 1.3 christos if (qctx->type == dns_rdatatype_any) { 10794 1.23 christos return query_respond_any(qctx); 10795 1.1 christos } 10796 1.1 christos 10797 1.3 christos result = query_zerottl_refetch(qctx); 10798 1.3 christos if (result != ISC_R_COMPLETE) { 10799 1.23 christos goto cleanup; 10800 1.1 christos } 10801 1.1 christos 10802 1.23 christos return query_respond(qctx); 10803 1.1 christos 10804 1.9 christos cleanup: 10805 1.23 christos return result; 10806 1.1 christos } 10807 1.1 christos 10808 1.1 christos /*% 10809 1.1 christos * Add SOA to the authority section when sending negative responses 10810 1.1 christos * (or to the additional section if sending negative responses triggered 10811 1.1 christos * by RPZ rewriting.) 10812 1.1 christos */ 10813 1.1 christos static isc_result_t 10814 1.1 christos query_addsoa(query_ctx_t *qctx, unsigned int override_ttl, 10815 1.9 christos dns_section_t section) { 10816 1.1 christos ns_client_t *client = qctx->client; 10817 1.20 christos dns_name_t *name = NULL; 10818 1.20 christos dns_dbnode_t *node = NULL; 10819 1.20 christos isc_result_t result, eresult = ISC_R_SUCCESS; 10820 1.1 christos dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 10821 1.1 christos dns_rdataset_t **sigrdatasetp = NULL; 10822 1.1 christos dns_clientinfomethods_t cm; 10823 1.1 christos dns_clientinfo_t ci; 10824 1.1 christos 10825 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addsoa"); 10826 1.1 christos 10827 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 10828 1.20 christos dns_clientinfo_init(&ci, client, NULL); 10829 1.1 christos 10830 1.1 christos /* 10831 1.1 christos * Don't add the SOA record for test which set "-T nosoa". 10832 1.1 christos */ 10833 1.23 christos if (((client->manager->sctx->options & NS_SERVER_NOSOA) != 0) && 10834 1.1 christos (!WANTDNSSEC(client) || !dns_rdataset_isassociated(qctx->rdataset))) 10835 1.1 christos { 10836 1.23 christos return ISC_R_SUCCESS; 10837 1.1 christos } 10838 1.1 christos 10839 1.1 christos /* 10840 1.1 christos * Get resources and make 'name' be the database origin. 10841 1.1 christos */ 10842 1.23 christos dns_message_gettempname(client->message, &name); 10843 1.14 christos 10844 1.14 christos /* 10845 1.14 christos * We'll be releasing 'name' before returning, so it's safe to 10846 1.14 christos * use clone instead of copying here. 10847 1.14 christos */ 10848 1.1 christos dns_name_clone(dns_db_origin(qctx->db), name); 10849 1.14 christos 10850 1.3 christos rdataset = ns_client_newrdataset(client); 10851 1.1 christos if (WANTDNSSEC(client) && dns_db_issecure(qctx->db)) { 10852 1.3 christos sigrdataset = ns_client_newrdataset(client); 10853 1.1 christos } 10854 1.1 christos 10855 1.1 christos /* 10856 1.1 christos * Find the SOA. 10857 1.1 christos */ 10858 1.1 christos result = dns_db_getoriginnode(qctx->db, &node); 10859 1.1 christos if (result == ISC_R_SUCCESS) { 10860 1.1 christos result = dns_db_findrdataset(qctx->db, node, qctx->version, 10861 1.9 christos dns_rdatatype_soa, 0, client->now, 10862 1.1 christos rdataset, sigrdataset); 10863 1.1 christos } else { 10864 1.1 christos dns_fixedname_t foundname; 10865 1.1 christos dns_name_t *fname; 10866 1.1 christos 10867 1.1 christos fname = dns_fixedname_initname(&foundname); 10868 1.1 christos 10869 1.1 christos result = dns_db_findext(qctx->db, name, qctx->version, 10870 1.1 christos dns_rdatatype_soa, 10871 1.9 christos client->query.dboptions, 0, &node, 10872 1.9 christos fname, &cm, &ci, rdataset, sigrdataset); 10873 1.1 christos } 10874 1.1 christos if (result != ISC_R_SUCCESS) { 10875 1.1 christos /* 10876 1.1 christos * This is bad. We tried to get the SOA RR at the zone top 10877 1.1 christos * and it didn't work! 10878 1.1 christos */ 10879 1.1 christos CTRACE(ISC_LOG_ERROR, "unable to find SOA RR at zone apex"); 10880 1.1 christos eresult = DNS_R_SERVFAIL; 10881 1.1 christos } else { 10882 1.1 christos /* 10883 1.1 christos * Extract the SOA MINIMUM. 10884 1.1 christos */ 10885 1.1 christos dns_rdata_soa_t soa; 10886 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 10887 1.1 christos result = dns_rdataset_first(rdataset); 10888 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 10889 1.1 christos dns_rdataset_current(rdataset, &rdata); 10890 1.1 christos result = dns_rdata_tostruct(&rdata, &soa, NULL); 10891 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 10892 1.1 christos 10893 1.9 christos if (override_ttl != UINT32_MAX && override_ttl < rdataset->ttl) 10894 1.1 christos { 10895 1.1 christos rdataset->ttl = override_ttl; 10896 1.9 christos if (sigrdataset != NULL) { 10897 1.1 christos sigrdataset->ttl = override_ttl; 10898 1.9 christos } 10899 1.1 christos } 10900 1.1 christos 10901 1.1 christos /* 10902 1.1 christos * Add the SOA and its SIG to the response, with the 10903 1.1 christos * TTLs adjusted per RFC2308 section 3. 10904 1.1 christos */ 10905 1.9 christos if (rdataset->ttl > soa.minimum) { 10906 1.1 christos rdataset->ttl = soa.minimum; 10907 1.9 christos } 10908 1.9 christos if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum) { 10909 1.1 christos sigrdataset->ttl = soa.minimum; 10910 1.9 christos } 10911 1.1 christos 10912 1.9 christos if (sigrdataset != NULL) { 10913 1.1 christos sigrdatasetp = &sigrdataset; 10914 1.9 christos } else { 10915 1.1 christos sigrdatasetp = NULL; 10916 1.9 christos } 10917 1.1 christos 10918 1.9 christos if (section == DNS_SECTION_ADDITIONAL) { 10919 1.1 christos rdataset->attributes |= DNS_RDATASETATTR_REQUIRED; 10920 1.9 christos } 10921 1.9 christos query_addrrset(qctx, &name, &rdataset, sigrdatasetp, NULL, 10922 1.9 christos section); 10923 1.1 christos } 10924 1.1 christos 10925 1.3 christos ns_client_putrdataset(client, &rdataset); 10926 1.9 christos if (sigrdataset != NULL) { 10927 1.3 christos ns_client_putrdataset(client, &sigrdataset); 10928 1.9 christos } 10929 1.9 christos if (name != NULL) { 10930 1.3 christos ns_client_releasename(client, &name); 10931 1.9 christos } 10932 1.9 christos if (node != NULL) { 10933 1.1 christos dns_db_detachnode(qctx->db, &node); 10934 1.9 christos } 10935 1.1 christos 10936 1.23 christos return eresult; 10937 1.1 christos } 10938 1.1 christos 10939 1.1 christos /*% 10940 1.1 christos * Add NS to authority section (used when the zone apex is already known). 10941 1.1 christos */ 10942 1.1 christos static isc_result_t 10943 1.1 christos query_addns(query_ctx_t *qctx) { 10944 1.1 christos ns_client_t *client = qctx->client; 10945 1.1 christos isc_result_t result, eresult; 10946 1.1 christos dns_name_t *name = NULL, *fname; 10947 1.1 christos dns_dbnode_t *node = NULL; 10948 1.1 christos dns_fixedname_t foundname; 10949 1.1 christos dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 10950 1.1 christos dns_rdataset_t **sigrdatasetp = NULL; 10951 1.1 christos dns_clientinfomethods_t cm; 10952 1.1 christos dns_clientinfo_t ci; 10953 1.1 christos 10954 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addns"); 10955 1.1 christos 10956 1.1 christos /* 10957 1.1 christos * Initialization. 10958 1.1 christos */ 10959 1.1 christos eresult = ISC_R_SUCCESS; 10960 1.1 christos fname = dns_fixedname_initname(&foundname); 10961 1.1 christos 10962 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 10963 1.20 christos dns_clientinfo_init(&ci, client, NULL); 10964 1.1 christos 10965 1.1 christos /* 10966 1.1 christos * Get resources and make 'name' be the database origin. 10967 1.1 christos */ 10968 1.23 christos dns_message_gettempname(client->message, &name); 10969 1.1 christos dns_name_clone(dns_db_origin(qctx->db), name); 10970 1.3 christos rdataset = ns_client_newrdataset(client); 10971 1.1 christos 10972 1.1 christos if (WANTDNSSEC(client) && dns_db_issecure(qctx->db)) { 10973 1.3 christos sigrdataset = ns_client_newrdataset(client); 10974 1.1 christos } 10975 1.1 christos 10976 1.1 christos /* 10977 1.1 christos * Find the NS rdataset. 10978 1.1 christos */ 10979 1.1 christos result = dns_db_getoriginnode(qctx->db, &node); 10980 1.1 christos if (result == ISC_R_SUCCESS) { 10981 1.1 christos result = dns_db_findrdataset(qctx->db, node, qctx->version, 10982 1.1 christos dns_rdatatype_ns, 0, client->now, 10983 1.1 christos rdataset, sigrdataset); 10984 1.1 christos } else { 10985 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addns: calling dns_db_find"); 10986 1.1 christos result = dns_db_findext(qctx->db, name, NULL, dns_rdatatype_ns, 10987 1.1 christos client->query.dboptions, 0, &node, 10988 1.1 christos fname, &cm, &ci, rdataset, sigrdataset); 10989 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_db_find complete"); 10990 1.1 christos } 10991 1.1 christos if (result != ISC_R_SUCCESS) { 10992 1.9 christos CTRACE(ISC_LOG_ERROR, "query_addns: " 10993 1.9 christos "dns_db_findrdataset or dns_db_find " 10994 1.9 christos "failed"); 10995 1.1 christos /* 10996 1.1 christos * This is bad. We tried to get the NS rdataset at the zone 10997 1.1 christos * top and it didn't work! 10998 1.1 christos */ 10999 1.1 christos eresult = DNS_R_SERVFAIL; 11000 1.1 christos } else { 11001 1.1 christos if (sigrdataset != NULL) { 11002 1.1 christos sigrdatasetp = &sigrdataset; 11003 1.1 christos } 11004 1.3 christos query_addrrset(qctx, &name, &rdataset, sigrdatasetp, NULL, 11005 1.1 christos DNS_SECTION_AUTHORITY); 11006 1.1 christos } 11007 1.1 christos 11008 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addns: cleanup"); 11009 1.3 christos ns_client_putrdataset(client, &rdataset); 11010 1.1 christos if (sigrdataset != NULL) { 11011 1.3 christos ns_client_putrdataset(client, &sigrdataset); 11012 1.1 christos } 11013 1.1 christos if (name != NULL) { 11014 1.3 christos ns_client_releasename(client, &name); 11015 1.1 christos } 11016 1.1 christos if (node != NULL) { 11017 1.1 christos dns_db_detachnode(qctx->db, &node); 11018 1.1 christos } 11019 1.1 christos 11020 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addns: done"); 11021 1.23 christos return eresult; 11022 1.1 christos } 11023 1.1 christos 11024 1.1 christos /*% 11025 1.1 christos * Find the zone cut and add the best NS rrset to the authority section. 11026 1.1 christos */ 11027 1.1 christos static void 11028 1.1 christos query_addbestns(query_ctx_t *qctx) { 11029 1.1 christos ns_client_t *client = qctx->client; 11030 1.1 christos dns_db_t *db = NULL, *zdb = NULL; 11031 1.1 christos dns_dbnode_t *node = NULL; 11032 1.1 christos dns_name_t *fname = NULL, *zfname = NULL; 11033 1.1 christos dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 11034 1.1 christos dns_rdataset_t *zrdataset = NULL, *zsigrdataset = NULL; 11035 1.3 christos bool is_zone = false, use_zone = false; 11036 1.1 christos isc_buffer_t *dbuf = NULL; 11037 1.1 christos isc_result_t result; 11038 1.1 christos dns_dbversion_t *version = NULL; 11039 1.1 christos dns_zone_t *zone = NULL; 11040 1.1 christos isc_buffer_t b; 11041 1.1 christos dns_clientinfomethods_t cm; 11042 1.1 christos dns_clientinfo_t ci; 11043 1.22 christos dns_name_t qname; 11044 1.1 christos 11045 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addbestns"); 11046 1.1 christos 11047 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 11048 1.20 christos dns_clientinfo_init(&ci, client, NULL); 11049 1.1 christos 11050 1.22 christos dns_name_init(&qname, NULL); 11051 1.22 christos dns_name_clone(client->query.qname, &qname); 11052 1.22 christos 11053 1.1 christos /* 11054 1.1 christos * Find the right database. 11055 1.1 christos */ 11056 1.22 christos do { 11057 1.23 christos result = query_getdb(client, &qname, dns_rdatatype_ns, 11058 1.23 christos (dns_getdb_options_t){ 0 }, &zone, &db, 11059 1.23 christos &version, &is_zone); 11060 1.22 christos if (result != ISC_R_SUCCESS) { 11061 1.22 christos goto cleanup; 11062 1.22 christos } 11063 1.22 christos 11064 1.22 christos /* 11065 1.22 christos * If this is a static stub zone look for a parent zone. 11066 1.22 christos */ 11067 1.22 christos if (zone != NULL && 11068 1.22 christos dns_zone_gettype(zone) == dns_zone_staticstub) 11069 1.22 christos { 11070 1.22 christos unsigned int labels = dns_name_countlabels(&qname); 11071 1.22 christos dns_db_detach(&db); 11072 1.22 christos dns_zone_detach(&zone); 11073 1.22 christos version = NULL; 11074 1.22 christos if (labels != 1) { 11075 1.22 christos dns_name_split(&qname, labels - 1, NULL, 11076 1.22 christos &qname); 11077 1.22 christos continue; 11078 1.22 christos } 11079 1.22 christos if (!USECACHE(client)) { 11080 1.22 christos goto cleanup; 11081 1.22 christos } 11082 1.22 christos dns_db_attach(client->view->cachedb, &db); 11083 1.22 christos is_zone = false; 11084 1.22 christos } 11085 1.22 christos break; 11086 1.22 christos } while (true); 11087 1.1 christos 11088 1.9 christos db_find: 11089 1.1 christos /* 11090 1.1 christos * We'll need some resources... 11091 1.1 christos */ 11092 1.3 christos dbuf = ns_client_getnamebuf(client); 11093 1.3 christos fname = ns_client_newname(client, dbuf, &b); 11094 1.3 christos rdataset = ns_client_newrdataset(client); 11095 1.1 christos 11096 1.1 christos /* 11097 1.1 christos * Get the RRSIGs if the client requested them or if we may 11098 1.1 christos * need to validate answers from the cache. 11099 1.1 christos */ 11100 1.1 christos if (WANTDNSSEC(client) || !is_zone) { 11101 1.3 christos sigrdataset = ns_client_newrdataset(client); 11102 1.1 christos } 11103 1.1 christos 11104 1.1 christos /* 11105 1.1 christos * Now look for the zonecut. 11106 1.1 christos */ 11107 1.1 christos if (is_zone) { 11108 1.9 christos result = dns_db_findext( 11109 1.9 christos db, client->query.qname, version, dns_rdatatype_ns, 11110 1.9 christos client->query.dboptions, client->now, &node, fname, &cm, 11111 1.9 christos &ci, rdataset, sigrdataset); 11112 1.1 christos if (result != DNS_R_DELEGATION) { 11113 1.1 christos goto cleanup; 11114 1.1 christos } 11115 1.1 christos if (USECACHE(client)) { 11116 1.3 christos ns_client_keepname(client, fname, dbuf); 11117 1.1 christos dns_db_detachnode(db, &node); 11118 1.1 christos SAVE(zdb, db); 11119 1.1 christos SAVE(zfname, fname); 11120 1.1 christos SAVE(zrdataset, rdataset); 11121 1.1 christos SAVE(zsigrdataset, sigrdataset); 11122 1.1 christos version = NULL; 11123 1.1 christos dns_db_attach(client->view->cachedb, &db); 11124 1.3 christos is_zone = false; 11125 1.1 christos goto db_find; 11126 1.1 christos } 11127 1.1 christos } else { 11128 1.9 christos result = dns_db_findzonecut( 11129 1.9 christos db, client->query.qname, client->query.dboptions, 11130 1.9 christos client->now, &node, fname, NULL, rdataset, sigrdataset); 11131 1.1 christos if (result == ISC_R_SUCCESS) { 11132 1.1 christos if (zfname != NULL && 11133 1.16 christos !dns_name_issubdomain(fname, zfname)) 11134 1.16 christos { 11135 1.1 christos /* 11136 1.1 christos * We found a zonecut in the cache, but our 11137 1.1 christos * zone delegation is better. 11138 1.1 christos */ 11139 1.3 christos use_zone = true; 11140 1.1 christos } 11141 1.1 christos } else if (result == ISC_R_NOTFOUND && zfname != NULL) { 11142 1.1 christos /* 11143 1.1 christos * We didn't find anything in the cache, but we 11144 1.1 christos * have a zone delegation, so use it. 11145 1.1 christos */ 11146 1.3 christos use_zone = true; 11147 1.1 christos } else { 11148 1.1 christos goto cleanup; 11149 1.1 christos } 11150 1.1 christos } 11151 1.1 christos 11152 1.1 christos if (use_zone) { 11153 1.3 christos ns_client_releasename(client, &fname); 11154 1.1 christos /* 11155 1.3 christos * We've already done ns_client_keepname() on 11156 1.1 christos * zfname, so we must set dbuf to NULL to 11157 1.1 christos * prevent query_addrrset() from trying to 11158 1.3 christos * call ns_client_keepname() again. 11159 1.1 christos */ 11160 1.1 christos dbuf = NULL; 11161 1.3 christos ns_client_putrdataset(client, &rdataset); 11162 1.1 christos if (sigrdataset != NULL) { 11163 1.3 christos ns_client_putrdataset(client, &sigrdataset); 11164 1.1 christos } 11165 1.1 christos 11166 1.1 christos if (node != NULL) { 11167 1.1 christos dns_db_detachnode(db, &node); 11168 1.1 christos } 11169 1.1 christos dns_db_detach(&db); 11170 1.1 christos 11171 1.1 christos RESTORE(db, zdb); 11172 1.1 christos RESTORE(fname, zfname); 11173 1.1 christos RESTORE(rdataset, zrdataset); 11174 1.1 christos RESTORE(sigrdataset, zsigrdataset); 11175 1.1 christos } 11176 1.1 christos 11177 1.1 christos /* 11178 1.1 christos * Attempt to validate RRsets that are pending or that are glue. 11179 1.1 christos */ 11180 1.1 christos if ((DNS_TRUST_PENDING(rdataset->trust) || 11181 1.1 christos (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust))) && 11182 1.1 christos !validate(client, db, fname, rdataset, sigrdataset) && 11183 1.1 christos !PENDINGOK(client->query.dboptions)) 11184 1.1 christos { 11185 1.1 christos goto cleanup; 11186 1.1 christos } 11187 1.1 christos 11188 1.1 christos if ((DNS_TRUST_GLUE(rdataset->trust) || 11189 1.1 christos (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) && 11190 1.1 christos !validate(client, db, fname, rdataset, sigrdataset) && 11191 1.1 christos SECURE(client) && WANTDNSSEC(client)) 11192 1.1 christos { 11193 1.1 christos goto cleanup; 11194 1.1 christos } 11195 1.1 christos 11196 1.1 christos /* 11197 1.1 christos * If the answer is secure only add NS records if they are secure 11198 1.1 christos * when the client may be looking for AD in the response. 11199 1.1 christos */ 11200 1.1 christos if (SECURE(client) && (WANTDNSSEC(client) || WANTAD(client)) && 11201 1.1 christos ((rdataset->trust != dns_trust_secure) || 11202 1.9 christos (sigrdataset != NULL && sigrdataset->trust != dns_trust_secure))) 11203 1.1 christos { 11204 1.1 christos goto cleanup; 11205 1.1 christos } 11206 1.1 christos 11207 1.1 christos /* 11208 1.1 christos * If the client doesn't want DNSSEC we can discard the sigrdataset 11209 1.1 christos * now. 11210 1.1 christos */ 11211 1.1 christos if (!WANTDNSSEC(client)) { 11212 1.3 christos ns_client_putrdataset(client, &sigrdataset); 11213 1.1 christos } 11214 1.1 christos 11215 1.3 christos query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf, 11216 1.1 christos DNS_SECTION_AUTHORITY); 11217 1.1 christos 11218 1.9 christos cleanup: 11219 1.1 christos if (rdataset != NULL) { 11220 1.3 christos ns_client_putrdataset(client, &rdataset); 11221 1.1 christos } 11222 1.1 christos if (sigrdataset != NULL) { 11223 1.3 christos ns_client_putrdataset(client, &sigrdataset); 11224 1.1 christos } 11225 1.1 christos if (fname != NULL) { 11226 1.3 christos ns_client_releasename(client, &fname); 11227 1.1 christos } 11228 1.1 christos if (node != NULL) { 11229 1.1 christos dns_db_detachnode(db, &node); 11230 1.1 christos } 11231 1.1 christos if (db != NULL) { 11232 1.1 christos dns_db_detach(&db); 11233 1.1 christos } 11234 1.1 christos if (zone != NULL) { 11235 1.1 christos dns_zone_detach(&zone); 11236 1.1 christos } 11237 1.1 christos if (zdb != NULL) { 11238 1.3 christos ns_client_putrdataset(client, &zrdataset); 11239 1.3 christos if (zsigrdataset != NULL) { 11240 1.3 christos ns_client_putrdataset(client, &zsigrdataset); 11241 1.3 christos } 11242 1.3 christos if (zfname != NULL) { 11243 1.3 christos ns_client_releasename(client, &zfname); 11244 1.3 christos } 11245 1.1 christos dns_db_detach(&zdb); 11246 1.1 christos } 11247 1.1 christos } 11248 1.1 christos 11249 1.1 christos static void 11250 1.9 christos query_addwildcardproof(query_ctx_t *qctx, bool ispositive, bool nodata) { 11251 1.1 christos ns_client_t *client = qctx->client; 11252 1.1 christos isc_buffer_t *dbuf, b; 11253 1.1 christos dns_name_t *name; 11254 1.1 christos dns_name_t *fname = NULL; 11255 1.1 christos dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 11256 1.1 christos dns_fixedname_t wfixed; 11257 1.1 christos dns_name_t *wname; 11258 1.1 christos dns_dbnode_t *node = NULL; 11259 1.1 christos unsigned int options; 11260 1.1 christos unsigned int olabels, nlabels, labels; 11261 1.1 christos isc_result_t result; 11262 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 11263 1.1 christos dns_rdata_nsec_t nsec; 11264 1.3 christos bool have_wname; 11265 1.1 christos int order; 11266 1.1 christos dns_fixedname_t cfixed; 11267 1.1 christos dns_name_t *cname; 11268 1.1 christos dns_clientinfomethods_t cm; 11269 1.1 christos dns_clientinfo_t ci; 11270 1.1 christos 11271 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof"); 11272 1.1 christos 11273 1.1 christos dns_clientinfomethods_init(&cm, ns_client_sourceip); 11274 1.20 christos dns_clientinfo_init(&ci, client, NULL); 11275 1.1 christos 11276 1.1 christos /* 11277 1.1 christos * If a name has been specifically flagged as needing 11278 1.1 christos * a wildcard proof then it will have been copied to 11279 1.1 christos * qctx->wildcardname. Otherwise we just use the client 11280 1.1 christos * QNAME. 11281 1.1 christos */ 11282 1.1 christos if (qctx->need_wildcardproof) { 11283 1.1 christos name = dns_fixedname_name(&qctx->wildcardname); 11284 1.1 christos } else { 11285 1.1 christos name = client->query.qname; 11286 1.1 christos } 11287 1.1 christos 11288 1.1 christos /* 11289 1.1 christos * Get the NOQNAME proof then if !ispositive 11290 1.1 christos * get the NOWILDCARD proof. 11291 1.1 christos * 11292 1.1 christos * DNS_DBFIND_NOWILD finds the NSEC records that covers the 11293 1.1 christos * name ignoring any wildcard. From the owner and next names 11294 1.1 christos * of this record you can compute which wildcard (if it exists) 11295 1.1 christos * will match by finding the longest common suffix of the 11296 1.1 christos * owner name and next names with the qname and prefixing that 11297 1.1 christos * with the wildcard label. 11298 1.1 christos * 11299 1.1 christos * e.g. 11300 1.1 christos * Given: 11301 1.1 christos * example SOA 11302 1.1 christos * example NSEC b.example 11303 1.1 christos * b.example A 11304 1.1 christos * b.example NSEC a.d.example 11305 1.1 christos * a.d.example A 11306 1.1 christos * a.d.example NSEC g.f.example 11307 1.1 christos * g.f.example A 11308 1.1 christos * g.f.example NSEC z.i.example 11309 1.1 christos * z.i.example A 11310 1.1 christos * z.i.example NSEC example 11311 1.1 christos * 11312 1.1 christos * QNAME: 11313 1.1 christos * a.example -> example NSEC b.example 11314 1.1 christos * owner common example 11315 1.1 christos * next common example 11316 1.1 christos * wild *.example 11317 1.1 christos * d.b.example -> b.example NSEC a.d.example 11318 1.1 christos * owner common b.example 11319 1.1 christos * next common example 11320 1.1 christos * wild *.b.example 11321 1.1 christos * a.f.example -> a.d.example NSEC g.f.example 11322 1.1 christos * owner common example 11323 1.1 christos * next common f.example 11324 1.1 christos * wild *.f.example 11325 1.1 christos * j.example -> z.i.example NSEC example 11326 1.1 christos * owner common example 11327 1.1 christos * next common example 11328 1.1 christos * wild *.example 11329 1.1 christos */ 11330 1.1 christos options = client->query.dboptions | DNS_DBFIND_NOWILD; 11331 1.1 christos wname = dns_fixedname_initname(&wfixed); 11332 1.9 christos again: 11333 1.3 christos have_wname = false; 11334 1.1 christos /* 11335 1.1 christos * We'll need some resources... 11336 1.1 christos */ 11337 1.3 christos dbuf = ns_client_getnamebuf(client); 11338 1.3 christos fname = ns_client_newname(client, dbuf, &b); 11339 1.3 christos rdataset = ns_client_newrdataset(client); 11340 1.3 christos sigrdataset = ns_client_newrdataset(client); 11341 1.1 christos 11342 1.1 christos result = dns_db_findext(qctx->db, name, qctx->version, 11343 1.9 christos dns_rdatatype_nsec, options, 0, &node, fname, 11344 1.9 christos &cm, &ci, rdataset, sigrdataset); 11345 1.9 christos if (node != NULL) { 11346 1.1 christos dns_db_detachnode(qctx->db, &node); 11347 1.9 christos } 11348 1.1 christos 11349 1.1 christos if (!dns_rdataset_isassociated(rdataset)) { 11350 1.1 christos /* 11351 1.1 christos * No NSEC proof available, return NSEC3 proofs instead. 11352 1.1 christos */ 11353 1.1 christos cname = dns_fixedname_initname(&cfixed); 11354 1.1 christos /* 11355 1.24 christos * Find the closest encloser. 11356 1.24 christos */ 11357 1.20 christos dns_name_copy(name, cname); 11358 1.24 christos while (result == DNS_R_NXDOMAIN) { 11359 1.24 christos labels = dns_name_countlabels(cname) - 1; 11360 1.24 christos /* 11361 1.24 christos * Sanity check. 11362 1.24 christos */ 11363 1.24 christos if (labels == 0U) { 11364 1.24 christos goto cleanup; 11365 1.9 christos } 11366 1.24 christos dns_name_split(cname, labels, NULL, cname); 11367 1.23 christos result = dns_db_findext(qctx->db, cname, qctx->version, 11368 1.23 christos dns_rdatatype_nsec, options, 0, 11369 1.23 christos NULL, fname, &cm, &ci, NULL, 11370 1.23 christos NULL); 11371 1.1 christos } 11372 1.1 christos /* 11373 1.1 christos * Add closest (provable) encloser NSEC3. 11374 1.1 christos */ 11375 1.9 christos query_findclosestnsec3(cname, qctx->db, qctx->version, client, 11376 1.9 christos rdataset, sigrdataset, fname, true, 11377 1.9 christos cname); 11378 1.9 christos if (!dns_rdataset_isassociated(rdataset)) { 11379 1.1 christos goto cleanup; 11380 1.9 christos } 11381 1.9 christos if (!ispositive) { 11382 1.3 christos query_addrrset(qctx, &fname, &rdataset, &sigrdataset, 11383 1.1 christos dbuf, DNS_SECTION_AUTHORITY); 11384 1.9 christos } 11385 1.1 christos 11386 1.1 christos /* 11387 1.1 christos * Replace resources which were consumed by query_addrrset. 11388 1.1 christos */ 11389 1.1 christos if (fname == NULL) { 11390 1.3 christos dbuf = ns_client_getnamebuf(client); 11391 1.3 christos fname = ns_client_newname(client, dbuf, &b); 11392 1.1 christos } 11393 1.1 christos 11394 1.9 christos if (rdataset == NULL) { 11395 1.3 christos rdataset = ns_client_newrdataset(client); 11396 1.9 christos } else if (dns_rdataset_isassociated(rdataset)) { 11397 1.1 christos dns_rdataset_disassociate(rdataset); 11398 1.9 christos } 11399 1.1 christos 11400 1.9 christos if (sigrdataset == NULL) { 11401 1.3 christos sigrdataset = ns_client_newrdataset(client); 11402 1.9 christos } else if (dns_rdataset_isassociated(sigrdataset)) { 11403 1.1 christos dns_rdataset_disassociate(sigrdataset); 11404 1.9 christos } 11405 1.1 christos 11406 1.1 christos /* 11407 1.1 christos * Add no qname proof. 11408 1.1 christos */ 11409 1.1 christos labels = dns_name_countlabels(cname) + 1; 11410 1.9 christos if (dns_name_countlabels(name) == labels) { 11411 1.20 christos dns_name_copy(name, wname); 11412 1.9 christos } else { 11413 1.1 christos dns_name_split(name, labels, NULL, wname); 11414 1.9 christos } 11415 1.1 christos 11416 1.9 christos query_findclosestnsec3(wname, qctx->db, qctx->version, client, 11417 1.9 christos rdataset, sigrdataset, fname, false, 11418 1.9 christos NULL); 11419 1.9 christos if (!dns_rdataset_isassociated(rdataset)) { 11420 1.1 christos goto cleanup; 11421 1.9 christos } 11422 1.9 christos query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf, 11423 1.9 christos DNS_SECTION_AUTHORITY); 11424 1.1 christos 11425 1.9 christos if (ispositive) { 11426 1.1 christos goto cleanup; 11427 1.9 christos } 11428 1.1 christos 11429 1.1 christos /* 11430 1.1 christos * Replace resources which were consumed by query_addrrset. 11431 1.1 christos */ 11432 1.1 christos if (fname == NULL) { 11433 1.3 christos dbuf = ns_client_getnamebuf(client); 11434 1.3 christos fname = ns_client_newname(client, dbuf, &b); 11435 1.1 christos } 11436 1.1 christos 11437 1.9 christos if (rdataset == NULL) { 11438 1.3 christos rdataset = ns_client_newrdataset(client); 11439 1.9 christos } else if (dns_rdataset_isassociated(rdataset)) { 11440 1.1 christos dns_rdataset_disassociate(rdataset); 11441 1.9 christos } 11442 1.1 christos 11443 1.9 christos if (sigrdataset == NULL) { 11444 1.3 christos sigrdataset = ns_client_newrdataset(client); 11445 1.9 christos } else if (dns_rdataset_isassociated(sigrdataset)) { 11446 1.1 christos dns_rdataset_disassociate(sigrdataset); 11447 1.9 christos } 11448 1.1 christos 11449 1.1 christos /* 11450 1.1 christos * Add the no wildcard proof. 11451 1.1 christos */ 11452 1.9 christos result = dns_name_concatenate(dns_wildcardname, cname, wname, 11453 1.9 christos NULL); 11454 1.9 christos if (result != ISC_R_SUCCESS) { 11455 1.1 christos goto cleanup; 11456 1.9 christos } 11457 1.1 christos 11458 1.9 christos query_findclosestnsec3(wname, qctx->db, qctx->version, client, 11459 1.9 christos rdataset, sigrdataset, fname, nodata, 11460 1.9 christos NULL); 11461 1.9 christos if (!dns_rdataset_isassociated(rdataset)) { 11462 1.1 christos goto cleanup; 11463 1.9 christos } 11464 1.9 christos query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf, 11465 1.9 christos DNS_SECTION_AUTHORITY); 11466 1.1 christos 11467 1.1 christos goto cleanup; 11468 1.1 christos } else if (result == DNS_R_NXDOMAIN) { 11469 1.9 christos if (!ispositive) { 11470 1.1 christos result = dns_rdataset_first(rdataset); 11471 1.9 christos } 11472 1.1 christos if (result == ISC_R_SUCCESS) { 11473 1.1 christos dns_rdataset_current(rdataset, &rdata); 11474 1.1 christos result = dns_rdata_tostruct(&rdata, &nsec, NULL); 11475 1.3 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 11476 1.1 christos (void)dns_name_fullcompare(name, fname, &order, 11477 1.1 christos &olabels); 11478 1.1 christos (void)dns_name_fullcompare(name, &nsec.next, &order, 11479 1.1 christos &nlabels); 11480 1.1 christos /* 11481 1.1 christos * Check for a pathological condition created when 11482 1.1 christos * serving some malformed signed zones and bail out. 11483 1.1 christos */ 11484 1.9 christos if (dns_name_countlabels(name) == nlabels) { 11485 1.1 christos goto cleanup; 11486 1.9 christos } 11487 1.1 christos 11488 1.9 christos if (olabels > nlabels) { 11489 1.1 christos dns_name_split(name, olabels, NULL, wname); 11490 1.9 christos } else { 11491 1.1 christos dns_name_split(name, nlabels, NULL, wname); 11492 1.9 christos } 11493 1.9 christos result = dns_name_concatenate(dns_wildcardname, wname, 11494 1.9 christos wname, NULL); 11495 1.9 christos if (result == ISC_R_SUCCESS) { 11496 1.3 christos have_wname = true; 11497 1.9 christos } 11498 1.1 christos dns_rdata_freestruct(&nsec); 11499 1.1 christos } 11500 1.9 christos query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf, 11501 1.9 christos DNS_SECTION_AUTHORITY); 11502 1.1 christos } 11503 1.3 christos if (rdataset != NULL) { 11504 1.3 christos ns_client_putrdataset(client, &rdataset); 11505 1.3 christos } 11506 1.3 christos if (sigrdataset != NULL) { 11507 1.3 christos ns_client_putrdataset(client, &sigrdataset); 11508 1.3 christos } 11509 1.3 christos if (fname != NULL) { 11510 1.3 christos ns_client_releasename(client, &fname); 11511 1.3 christos } 11512 1.1 christos if (have_wname) { 11513 1.9 christos ispositive = true; /* prevent loop */ 11514 1.1 christos if (!dns_name_equal(name, wname)) { 11515 1.1 christos name = wname; 11516 1.1 christos goto again; 11517 1.1 christos } 11518 1.1 christos } 11519 1.9 christos cleanup: 11520 1.3 christos if (rdataset != NULL) { 11521 1.3 christos ns_client_putrdataset(client, &rdataset); 11522 1.3 christos } 11523 1.3 christos if (sigrdataset != NULL) { 11524 1.3 christos ns_client_putrdataset(client, &sigrdataset); 11525 1.3 christos } 11526 1.3 christos if (fname != NULL) { 11527 1.3 christos ns_client_releasename(client, &fname); 11528 1.3 christos } 11529 1.1 christos } 11530 1.1 christos 11531 1.1 christos /*% 11532 1.1 christos * Add NS records, and NSEC/NSEC3 wildcard proof records if needed, 11533 1.1 christos * to the authority section. 11534 1.1 christos */ 11535 1.1 christos static void 11536 1.1 christos query_addauth(query_ctx_t *qctx) { 11537 1.1 christos CCTRACE(ISC_LOG_DEBUG(3), "query_addauth"); 11538 1.1 christos /* 11539 1.1 christos * Add NS records to the authority section (if we haven't already 11540 1.1 christos * added them to the answer section). 11541 1.1 christos */ 11542 1.1 christos if (!qctx->want_restart && !NOAUTHORITY(qctx->client)) { 11543 1.1 christos if (qctx->is_zone) { 11544 1.1 christos if (!qctx->answer_has_ns) { 11545 1.1 christos (void)query_addns(qctx); 11546 1.1 christos } 11547 1.1 christos } else if (!qctx->answer_has_ns && 11548 1.16 christos qctx->qtype != dns_rdatatype_ns) 11549 1.16 christos { 11550 1.1 christos if (qctx->fname != NULL) { 11551 1.3 christos ns_client_releasename(qctx->client, 11552 1.3 christos &qctx->fname); 11553 1.1 christos } 11554 1.1 christos query_addbestns(qctx); 11555 1.1 christos } 11556 1.1 christos } 11557 1.1 christos 11558 1.1 christos /* 11559 1.1 christos * Add NSEC records to the authority section if they're needed for 11560 1.1 christos * DNSSEC wildcard proofs. 11561 1.1 christos */ 11562 1.9 christos if (qctx->need_wildcardproof && dns_db_issecure(qctx->db)) { 11563 1.3 christos query_addwildcardproof(qctx, true, false); 11564 1.9 christos } 11565 1.1 christos } 11566 1.1 christos 11567 1.1 christos /* 11568 1.1 christos * Find the sort order of 'rdata' in the topology-like 11569 1.1 christos * ACL forming the second element in a 2-element top-level 11570 1.1 christos * sortlist statement. 11571 1.1 christos */ 11572 1.1 christos static int 11573 1.1 christos query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) { 11574 1.1 christos isc_netaddr_t netaddr; 11575 1.1 christos 11576 1.9 christos if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) { 11577 1.23 christos return INT_MAX; 11578 1.9 christos } 11579 1.23 christos return ns_sortlist_addrorder2(&netaddr, arg); 11580 1.1 christos } 11581 1.1 christos 11582 1.1 christos /* 11583 1.1 christos * Find the sort order of 'rdata' in the matching element 11584 1.1 christos * of a 1-element top-level sortlist statement. 11585 1.1 christos */ 11586 1.1 christos static int 11587 1.1 christos query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) { 11588 1.1 christos isc_netaddr_t netaddr; 11589 1.1 christos 11590 1.9 christos if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) { 11591 1.23 christos return INT_MAX; 11592 1.9 christos } 11593 1.23 christos return ns_sortlist_addrorder1(&netaddr, arg); 11594 1.1 christos } 11595 1.1 christos 11596 1.1 christos /* 11597 1.1 christos * Find the sortlist statement that applies to 'client' and set up 11598 1.1 christos * the sortlist info in in client->message appropriately. 11599 1.1 christos */ 11600 1.1 christos static void 11601 1.1 christos query_setup_sortlist(query_ctx_t *qctx) { 11602 1.1 christos isc_netaddr_t netaddr; 11603 1.1 christos ns_client_t *client = qctx->client; 11604 1.20 christos dns_aclenv_t *env = client->manager->aclenv; 11605 1.20 christos dns_acl_t *acl = NULL; 11606 1.20 christos dns_aclelement_t *elt = NULL; 11607 1.20 christos void *order_arg = NULL; 11608 1.1 christos 11609 1.1 christos isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); 11610 1.9 christos switch (ns_sortlist_setup(client->view->sortlist, env, &netaddr, 11611 1.16 christos &order_arg)) 11612 1.16 christos { 11613 1.1 christos case NS_SORTLISTTYPE_1ELEMENT: 11614 1.20 christos elt = order_arg; 11615 1.1 christos dns_message_setsortorder(client->message, 11616 1.9 christos query_sortlist_order_1element, env, 11617 1.20 christos NULL, elt); 11618 1.1 christos break; 11619 1.1 christos case NS_SORTLISTTYPE_2ELEMENT: 11620 1.20 christos acl = order_arg; 11621 1.1 christos dns_message_setsortorder(client->message, 11622 1.9 christos query_sortlist_order_2element, env, 11623 1.20 christos acl, NULL); 11624 1.20 christos dns_acl_detach(&acl); 11625 1.1 christos break; 11626 1.1 christos case NS_SORTLISTTYPE_NONE: 11627 1.1 christos break; 11628 1.1 christos default: 11629 1.15 christos UNREACHABLE(); 11630 1.1 christos } 11631 1.1 christos } 11632 1.1 christos 11633 1.1 christos /* 11634 1.1 christos * When sending a referral, if the answer to the question is 11635 1.1 christos * in the glue, sort it to the start of the additional section. 11636 1.1 christos */ 11637 1.15 christos static void 11638 1.1 christos query_glueanswer(query_ctx_t *qctx) { 11639 1.1 christos const dns_namelist_t *secs = qctx->client->message->sections; 11640 1.1 christos const dns_section_t section = DNS_SECTION_ADDITIONAL; 11641 1.1 christos dns_name_t *name; 11642 1.1 christos dns_message_t *msg; 11643 1.1 christos dns_rdataset_t *rdataset = NULL; 11644 1.1 christos 11645 1.1 christos if (!ISC_LIST_EMPTY(secs[DNS_SECTION_ANSWER]) || 11646 1.1 christos qctx->client->message->rcode != dns_rcode_noerror || 11647 1.1 christos (qctx->qtype != dns_rdatatype_a && 11648 1.1 christos qctx->qtype != dns_rdatatype_aaaa)) 11649 1.1 christos { 11650 1.1 christos return; 11651 1.1 christos } 11652 1.1 christos 11653 1.1 christos msg = qctx->client->message; 11654 1.9 christos for (name = ISC_LIST_HEAD(msg->sections[section]); name != NULL; 11655 1.1 christos name = ISC_LIST_NEXT(name, link)) 11656 1.9 christos { 11657 1.1 christos if (dns_name_equal(name, qctx->client->query.qname)) { 11658 1.1 christos for (rdataset = ISC_LIST_HEAD(name->list); 11659 1.1 christos rdataset != NULL; 11660 1.1 christos rdataset = ISC_LIST_NEXT(rdataset, link)) 11661 1.9 christos { 11662 1.9 christos if (rdataset->type == qctx->qtype) { 11663 1.1 christos break; 11664 1.9 christos } 11665 1.9 christos } 11666 1.1 christos break; 11667 1.1 christos } 11668 1.9 christos } 11669 1.1 christos if (rdataset != NULL) { 11670 1.1 christos ISC_LIST_UNLINK(msg->sections[section], name, link); 11671 1.1 christos ISC_LIST_PREPEND(msg->sections[section], name, link); 11672 1.1 christos ISC_LIST_UNLINK(name->list, rdataset, link); 11673 1.1 christos ISC_LIST_PREPEND(name->list, rdataset, link); 11674 1.1 christos rdataset->attributes |= DNS_RDATASETATTR_REQUIRED; 11675 1.1 christos } 11676 1.1 christos } 11677 1.1 christos 11678 1.3 christos isc_result_t 11679 1.3 christos ns_query_done(query_ctx_t *qctx) { 11680 1.20 christos isc_result_t result = ISC_R_UNSET; 11681 1.1 christos const dns_namelist_t *secs = qctx->client->message->sections; 11682 1.23 christos bool partial_result_with_servfail = false; 11683 1.1 christos 11684 1.3 christos CCTRACE(ISC_LOG_DEBUG(3), "ns_query_done"); 11685 1.3 christos 11686 1.3 christos CALL_HOOK(NS_QUERY_DONE_BEGIN, qctx); 11687 1.1 christos 11688 1.1 christos /* 11689 1.1 christos * General cleanup. 11690 1.1 christos */ 11691 1.1 christos qctx->rpz_st = qctx->client->query.rpz_st; 11692 1.1 christos if (qctx->rpz_st != NULL && 11693 1.16 christos (qctx->rpz_st->state & DNS_RPZ_RECURSING) == 0) 11694 1.16 christos { 11695 1.1 christos rpz_match_clear(qctx->rpz_st); 11696 1.1 christos qctx->rpz_st->state &= ~DNS_RPZ_DONE_QNAME; 11697 1.1 christos } 11698 1.1 christos 11699 1.1 christos qctx_clean(qctx); 11700 1.1 christos qctx_freedata(qctx); 11701 1.1 christos 11702 1.1 christos /* 11703 1.1 christos * Clear the AA bit if we're not authoritative. 11704 1.1 christos */ 11705 1.1 christos if (qctx->client->query.restarts == 0 && !qctx->authoritative) { 11706 1.1 christos qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA; 11707 1.1 christos } 11708 1.1 christos 11709 1.1 christos /* 11710 1.1 christos * Do we need to restart the query (e.g. for CNAME chaining)? 11711 1.1 christos */ 11712 1.22 christos if (qctx->want_restart) { 11713 1.22 christos if (qctx->client->query.restarts < 11714 1.22 christos qctx->client->view->max_restarts) 11715 1.22 christos { 11716 1.23 christos query_ctx_t *saved_qctx = NULL; 11717 1.22 christos qctx->client->query.restarts++; 11718 1.23 christos saved_qctx = isc_mem_get(qctx->client->manager->mctx, 11719 1.23 christos sizeof(*saved_qctx)); 11720 1.23 christos qctx_save(qctx, saved_qctx); 11721 1.23 christos isc_nmhandle_attach(qctx->client->handle, 11722 1.23 christos &qctx->client->restarthandle); 11723 1.23 christos isc_async_run(qctx->client->manager->loop, 11724 1.23 christos async_restart, saved_qctx); 11725 1.23 christos return DNS_R_CONTINUE; 11726 1.22 christos } else { 11727 1.22 christos /* 11728 1.22 christos * This is e.g. a long CNAME chain which we cut short. 11729 1.22 christos */ 11730 1.22 christos qctx->client->query.attributes |= 11731 1.22 christos NS_QUERYATTR_PARTIALANSWER; 11732 1.22 christos qctx->client->message->rcode = dns_rcode_servfail; 11733 1.22 christos qctx->result = DNS_R_SERVFAIL; 11734 1.22 christos 11735 1.22 christos /* 11736 1.22 christos * Send the answer back with a SERVFAIL result even 11737 1.22 christos * if recursion was requested. 11738 1.22 christos */ 11739 1.22 christos partial_result_with_servfail = true; 11740 1.22 christos 11741 1.24 christos dns_ede_add(&qctx->client->edectx, DNS_EDE_OTHER, 11742 1.24 christos "max. restarts reached"); 11743 1.22 christos ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT, 11744 1.22 christos NS_LOGMODULE_QUERY, ISC_LOG_INFO, 11745 1.22 christos "query iterations limit reached"); 11746 1.22 christos } 11747 1.1 christos } 11748 1.1 christos 11749 1.1 christos if (qctx->result != ISC_R_SUCCESS && 11750 1.22 christos (!PARTIALANSWER(qctx->client) || 11751 1.22 christos (WANTRECURSION(qctx->client) && !partial_result_with_servfail) || 11752 1.1 christos qctx->result == DNS_R_DROP)) 11753 1.1 christos { 11754 1.1 christos if (qctx->result == DNS_R_DUPLICATE || 11755 1.16 christos qctx->result == DNS_R_DROP) 11756 1.16 christos { 11757 1.1 christos /* 11758 1.1 christos * This was a duplicate query that we are 11759 1.1 christos * recursing on or the result of rate limiting. 11760 1.1 christos * Don't send a response now for a duplicate query, 11761 1.1 christos * because the original will still cause a response. 11762 1.1 christos */ 11763 1.1 christos query_next(qctx->client, qctx->result); 11764 1.1 christos } else { 11765 1.1 christos /* 11766 1.1 christos * If we don't have any answer to give the client, 11767 1.1 christos * or if the client requested recursion and thus wanted 11768 1.1 christos * the complete answer, send an error response. 11769 1.1 christos */ 11770 1.1 christos INSIST(qctx->line >= 0); 11771 1.1 christos query_error(qctx->client, qctx->result, qctx->line); 11772 1.1 christos } 11773 1.1 christos 11774 1.3 christos qctx->detach_client = true; 11775 1.23 christos return qctx->result; 11776 1.1 christos } 11777 1.1 christos 11778 1.1 christos /* 11779 1.1 christos * If we're recursing then just return; the query will 11780 1.1 christos * resume when recursion ends. 11781 1.1 christos */ 11782 1.11 christos if (RECURSING(qctx->client) && 11783 1.13 christos (!QUERY_STALETIMEOUT(&qctx->client->query) || 11784 1.23 christos qctx->options.stalefirst)) 11785 1.11 christos { 11786 1.23 christos return qctx->result; 11787 1.1 christos } 11788 1.1 christos 11789 1.1 christos /* 11790 1.1 christos * We are done. Set up sortlist data for the message 11791 1.1 christos * rendering code, sort the answer to the front of the 11792 1.1 christos * additional section if necessary, make a final tweak 11793 1.1 christos * to the AA bit if the auth-nxdomain config option 11794 1.1 christos * says so, then render and send the response. 11795 1.1 christos */ 11796 1.13 christos query_setup_sortlist(qctx); 11797 1.13 christos query_glueanswer(qctx); 11798 1.1 christos 11799 1.1 christos if (qctx->client->message->rcode == dns_rcode_nxdomain && 11800 1.10 christos qctx->view->auth_nxdomain) 11801 1.1 christos { 11802 1.1 christos qctx->client->message->flags |= DNS_MESSAGEFLAG_AA; 11803 1.1 christos } 11804 1.1 christos 11805 1.1 christos /* 11806 1.1 christos * If the response is somehow unexpected for the client and this 11807 1.1 christos * is a result of recursion, return an error to the caller 11808 1.1 christos * to indicate it may need to be logged. 11809 1.1 christos */ 11810 1.1 christos if (qctx->resuming && 11811 1.1 christos (ISC_LIST_EMPTY(secs[DNS_SECTION_ANSWER]) || 11812 1.1 christos qctx->client->message->rcode != dns_rcode_noerror)) 11813 1.1 christos { 11814 1.1 christos qctx->result = ISC_R_FAILURE; 11815 1.1 christos } 11816 1.1 christos 11817 1.3 christos CALL_HOOK(NS_QUERY_DONE_SEND, qctx); 11818 1.3 christos 11819 1.1 christos query_send(qctx->client); 11820 1.15 christos 11821 1.23 christos qctx->detach_client = true; 11822 1.23 christos 11823 1.23 christos return qctx->result; 11824 1.3 christos 11825 1.9 christos cleanup: 11826 1.24 christos /* 11827 1.24 christos * We'd only get here if one of the hooks above 11828 1.24 christos * (NS_QUERY_DONE_BEGIN or NS_QUERY_DONE_SEND) returned 11829 1.24 christos * NS_HOOK_RETURN. Some housekeeping may be needed. 11830 1.24 christos */ 11831 1.24 christos qctx_clean(qctx); 11832 1.24 christos qctx_freedata(qctx); 11833 1.24 christos if (!qctx->async) { 11834 1.24 christos qctx->detach_client = true; 11835 1.24 christos query_error(qctx->client, DNS_R_SERVFAIL, __LINE__); 11836 1.24 christos } 11837 1.23 christos return result; 11838 1.1 christos } 11839 1.1 christos 11840 1.15 christos static void 11841 1.1 christos log_tat(ns_client_t *client) { 11842 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 11843 1.1 christos char clientbuf[ISC_NETADDR_FORMATSIZE]; 11844 1.3 christos char classbuf[DNS_RDATACLASS_FORMATSIZE]; 11845 1.1 christos isc_netaddr_t netaddr; 11846 1.1 christos char *tags = NULL; 11847 1.1 christos size_t taglen = 0; 11848 1.1 christos 11849 1.1 christos if (!isc_log_wouldlog(ns_lctx, ISC_LOG_INFO)) { 11850 1.1 christos return; 11851 1.1 christos } 11852 1.1 christos 11853 1.1 christos if ((client->query.qtype != dns_rdatatype_null || 11854 1.1 christos !dns_name_istat(client->query.qname)) && 11855 1.1 christos (client->keytag == NULL || 11856 1.1 christos client->query.qtype != dns_rdatatype_dnskey)) 11857 1.1 christos { 11858 1.1 christos return; 11859 1.1 christos } 11860 1.1 christos 11861 1.1 christos isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); 11862 1.1 christos dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); 11863 1.3 christos isc_netaddr_format(&netaddr, clientbuf, sizeof(clientbuf)); 11864 1.3 christos dns_rdataclass_format(client->view->rdclass, classbuf, 11865 1.3 christos sizeof(classbuf)); 11866 1.1 christos 11867 1.1 christos if (client->query.qtype == dns_rdatatype_dnskey) { 11868 1.3 christos uint16_t keytags = client->keytag_len / 2; 11869 1.1 christos size_t len = taglen = sizeof("65000") * keytags + 1; 11870 1.23 christos char *cp = tags = isc_mem_get(client->manager->mctx, taglen); 11871 1.1 christos int i = 0; 11872 1.1 christos 11873 1.1 christos INSIST(client->keytag != NULL); 11874 1.1 christos if (tags != NULL) { 11875 1.1 christos while (keytags-- > 0U) { 11876 1.1 christos int n; 11877 1.3 christos uint16_t keytag; 11878 1.1 christos keytag = (client->keytag[i * 2] << 8) | 11879 1.1 christos client->keytag[i * 2 + 1]; 11880 1.1 christos n = snprintf(cp, len, " %u", keytag); 11881 1.1 christos if (n > 0 && (size_t)n <= len) { 11882 1.1 christos cp += n; 11883 1.1 christos len -= n; 11884 1.1 christos i++; 11885 1.1 christos } else { 11886 1.1 christos break; 11887 1.1 christos } 11888 1.1 christos } 11889 1.1 christos } 11890 1.1 christos } 11891 1.1 christos 11892 1.1 christos isc_log_write(ns_lctx, NS_LOGCATEGORY_TAT, NS_LOGMODULE_QUERY, 11893 1.1 christos ISC_LOG_INFO, "trust-anchor-telemetry '%s/%s' from %s%s", 11894 1.9 christos namebuf, classbuf, clientbuf, tags != NULL ? tags : ""); 11895 1.1 christos if (tags != NULL) { 11896 1.23 christos isc_mem_put(client->manager->mctx, tags, taglen); 11897 1.1 christos } 11898 1.1 christos } 11899 1.1 christos 11900 1.15 christos static void 11901 1.1 christos log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) { 11902 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 11903 1.3 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 11904 1.3 christos char classbuf[DNS_RDATACLASS_FORMATSIZE]; 11905 1.1 christos char onbuf[ISC_NETADDR_FORMATSIZE]; 11906 1.23 christos char ecsbuf[NS_CLIENT_ECS_FORMATSIZE] = { 0 }; 11907 1.23 christos char flagsbuf[NS_CLIENT_FLAGS_FORMATSIZE] = { 0 }; 11908 1.1 christos dns_rdataset_t *rdataset; 11909 1.1 christos int level = ISC_LOG_INFO; 11910 1.1 christos 11911 1.9 christos if (!isc_log_wouldlog(ns_lctx, level)) { 11912 1.1 christos return; 11913 1.9 christos } 11914 1.1 christos 11915 1.1 christos rdataset = ISC_LIST_HEAD(client->query.qname->list); 11916 1.1 christos INSIST(rdataset != NULL); 11917 1.1 christos dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); 11918 1.3 christos dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf)); 11919 1.3 christos dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); 11920 1.1 christos isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf)); 11921 1.1 christos 11922 1.1 christos if (HAVEECS(client)) { 11923 1.23 christos ns_client_log_ecs(client, ecsbuf, sizeof(ecsbuf)); 11924 1.1 christos } 11925 1.23 christos ns_client_log_flags(client, flags, extflags, flagsbuf, 11926 1.23 christos sizeof(flagsbuf)); 11927 1.1 christos 11928 1.9 christos ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, level, 11929 1.23 christos "query: %s %s %s %s (%s)%s", namebuf, classbuf, typebuf, 11930 1.23 christos flagsbuf, onbuf, ecsbuf); 11931 1.1 christos } 11932 1.1 christos 11933 1.15 christos static void 11934 1.1 christos log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) { 11935 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 11936 1.3 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 11937 1.3 christos char classbuf[DNS_RDATACLASS_FORMATSIZE]; 11938 1.1 christos const char *namep, *typep, *classp, *sep1, *sep2; 11939 1.1 christos dns_rdataset_t *rdataset; 11940 1.1 christos 11941 1.9 christos if (!isc_log_wouldlog(ns_lctx, level)) { 11942 1.1 christos return; 11943 1.9 christos } 11944 1.1 christos 11945 1.1 christos namep = typep = classp = sep1 = sep2 = ""; 11946 1.1 christos 11947 1.1 christos /* 11948 1.1 christos * Query errors can happen for various reasons. In some cases we cannot 11949 1.1 christos * even assume the query contains a valid question section, so we should 11950 1.1 christos * expect exceptional cases. 11951 1.1 christos */ 11952 1.1 christos if (client->query.origqname != NULL) { 11953 1.1 christos dns_name_format(client->query.origqname, namebuf, 11954 1.1 christos sizeof(namebuf)); 11955 1.1 christos namep = namebuf; 11956 1.1 christos sep1 = " for "; 11957 1.1 christos 11958 1.1 christos rdataset = ISC_LIST_HEAD(client->query.origqname->list); 11959 1.1 christos if (rdataset != NULL) { 11960 1.3 christos dns_rdataclass_format(rdataset->rdclass, classbuf, 11961 1.3 christos sizeof(classbuf)); 11962 1.3 christos classp = classbuf; 11963 1.3 christos dns_rdatatype_format(rdataset->type, typebuf, 11964 1.3 christos sizeof(typebuf)); 11965 1.3 christos typep = typebuf; 11966 1.1 christos sep2 = "/"; 11967 1.1 christos } 11968 1.1 christos } 11969 1.1 christos 11970 1.1 christos ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY, 11971 1.1 christos level, "query failed (%s)%s%s%s%s%s%s at %s:%d", 11972 1.9 christos isc_result_totext(result), sep1, namep, sep2, classp, 11973 1.9 christos sep2, typep, __FILE__, line); 11974 1.1 christos } 11975 1.1 christos 11976 1.1 christos void 11977 1.11 christos ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) { 11978 1.1 christos isc_result_t result; 11979 1.8 christos dns_message_t *message; 11980 1.1 christos dns_rdataset_t *rdataset; 11981 1.1 christos dns_rdatatype_t qtype; 11982 1.8 christos unsigned int saved_extflags; 11983 1.8 christos unsigned int saved_flags; 11984 1.1 christos 11985 1.1 christos REQUIRE(NS_CLIENT_VALID(client)); 11986 1.1 christos 11987 1.11 christos /* 11988 1.11 christos * Attach to the request handle 11989 1.11 christos */ 11990 1.11 christos isc_nmhandle_attach(handle, &client->reqhandle); 11991 1.11 christos 11992 1.8 christos message = client->message; 11993 1.8 christos saved_extflags = client->extflags; 11994 1.8 christos saved_flags = client->message->flags; 11995 1.8 christos 11996 1.1 christos CTRACE(ISC_LOG_DEBUG(3), "ns_query_start"); 11997 1.1 christos 11998 1.1 christos /* 11999 1.1 christos * Ensure that appropriate cleanups occur. 12000 1.1 christos */ 12001 1.9 christos client->cleanup = query_cleanup; 12002 1.1 christos 12003 1.9 christos if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) { 12004 1.9 christos client->query.attributes |= NS_QUERYATTR_WANTRECURSION; 12005 1.1 christos } 12006 1.1 christos 12007 1.9 christos if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0) { 12008 1.1 christos client->attributes |= NS_CLIENTATTR_WANTDNSSEC; 12009 1.9 christos } 12010 1.1 christos 12011 1.1 christos switch (client->view->minimalresponses) { 12012 1.1 christos case dns_minimal_no: 12013 1.1 christos break; 12014 1.1 christos case dns_minimal_yes: 12015 1.1 christos client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 12016 1.1 christos NS_QUERYATTR_NOADDITIONAL); 12017 1.1 christos break; 12018 1.1 christos case dns_minimal_noauth: 12019 1.1 christos client->query.attributes |= NS_QUERYATTR_NOAUTHORITY; 12020 1.1 christos break; 12021 1.1 christos case dns_minimal_noauthrec: 12022 1.9 christos if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) { 12023 1.1 christos client->query.attributes |= NS_QUERYATTR_NOAUTHORITY; 12024 1.9 christos } 12025 1.1 christos break; 12026 1.1 christos } 12027 1.1 christos 12028 1.1 christos if (client->view->cachedb == NULL || !client->view->recursion) { 12029 1.1 christos /* 12030 1.1 christos * We don't have a cache. Turn off cache support and 12031 1.1 christos * recursion. 12032 1.1 christos */ 12033 1.9 christos client->query.attributes &= ~(NS_QUERYATTR_RECURSIONOK | 12034 1.9 christos NS_QUERYATTR_CACHEOK); 12035 1.1 christos client->attributes |= NS_CLIENTATTR_NOSETFC; 12036 1.1 christos } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 || 12037 1.9 christos (message->flags & DNS_MESSAGEFLAG_RD) == 0) 12038 1.9 christos { 12039 1.1 christos /* 12040 1.1 christos * If the client isn't allowed to recurse (due to 12041 1.1 christos * "recursion no", the allow-recursion ACL, or the 12042 1.1 christos * lack of a resolver in this view), or if it 12043 1.1 christos * doesn't want recursion, turn recursion off. 12044 1.1 christos */ 12045 1.1 christos client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK; 12046 1.1 christos client->attributes |= NS_CLIENTATTR_NOSETFC; 12047 1.1 christos } 12048 1.1 christos 12049 1.1 christos /* 12050 1.1 christos * Check for multiple question queries, since edns1 is dead. 12051 1.1 christos */ 12052 1.1 christos if (message->counts[DNS_SECTION_QUESTION] > 1) { 12053 1.1 christos query_error(client, DNS_R_FORMERR, __LINE__); 12054 1.1 christos return; 12055 1.1 christos } 12056 1.1 christos 12057 1.1 christos /* 12058 1.1 christos * Get the question name. 12059 1.1 christos */ 12060 1.1 christos result = dns_message_firstname(message, DNS_SECTION_QUESTION); 12061 1.1 christos if (result != ISC_R_SUCCESS) { 12062 1.1 christos query_error(client, result, __LINE__); 12063 1.1 christos return; 12064 1.1 christos } 12065 1.1 christos dns_message_currentname(message, DNS_SECTION_QUESTION, 12066 1.1 christos &client->query.qname); 12067 1.1 christos client->query.origqname = client->query.qname; 12068 1.1 christos result = dns_message_nextname(message, DNS_SECTION_QUESTION); 12069 1.1 christos if (result != ISC_R_NOMORE) { 12070 1.1 christos if (result == ISC_R_SUCCESS) { 12071 1.1 christos /* 12072 1.1 christos * There's more than one QNAME in the question 12073 1.1 christos * section. 12074 1.1 christos */ 12075 1.1 christos query_error(client, DNS_R_FORMERR, __LINE__); 12076 1.9 christos } else { 12077 1.1 christos query_error(client, result, __LINE__); 12078 1.9 christos } 12079 1.1 christos return; 12080 1.1 christos } 12081 1.1 christos 12082 1.23 christos if ((client->manager->sctx->options & NS_SERVER_LOGQUERIES) != 0) { 12083 1.1 christos log_query(client, saved_flags, saved_extflags); 12084 1.9 christos } 12085 1.1 christos 12086 1.1 christos /* 12087 1.1 christos * Check for meta-queries like IXFR and AXFR. 12088 1.1 christos */ 12089 1.1 christos rdataset = ISC_LIST_HEAD(client->query.qname->list); 12090 1.1 christos INSIST(rdataset != NULL); 12091 1.1 christos client->query.qtype = qtype = rdataset->type; 12092 1.23 christos dns_rdatatypestats_increment(client->manager->sctx->rcvquerystats, 12093 1.23 christos qtype); 12094 1.1 christos 12095 1.1 christos log_tat(client); 12096 1.1 christos 12097 1.1 christos if (dns_rdatatype_ismeta(qtype)) { 12098 1.1 christos switch (qtype) { 12099 1.1 christos case dns_rdatatype_any: 12100 1.1 christos break; /* Let the query logic handle it. */ 12101 1.1 christos case dns_rdatatype_ixfr: 12102 1.1 christos case dns_rdatatype_axfr: 12103 1.20 christos if (isc_nm_is_http_handle(handle)) { 12104 1.20 christos /* 12105 1.20 christos * We cannot use DoH for zone transfers. 12106 1.20 christos * According to RFC 8484 a DoH request contains 12107 1.20 christos * exactly one DNS message (see Section 6: 12108 1.20 christos * Definition of the "application/dns-message" 12109 1.20 christos * Media Type). 12110 1.20 christos * 12111 1.20 christos * This makes DoH unsuitable for zone transfers 12112 1.20 christos * as often (and usually!) these need more than 12113 1.20 christos * one DNS message, especially for larger zones. 12114 1.20 christos * As zone transfers over DoH are not (yet) 12115 1.20 christos * standardised, nor discussed in RFC 8484, 12116 1.20 christos * the best thing we can do is to return "not 12117 1.20 christos * implemented". 12118 1.20 christos */ 12119 1.20 christos query_error(client, DNS_R_NOTIMP, __LINE__); 12120 1.20 christos return; 12121 1.20 christos } 12122 1.23 christos if (isc_nm_socket_type(handle) == 12123 1.23 christos isc_nm_streamdnssocket) 12124 1.23 christos { 12125 1.20 christos /* 12126 1.20 christos * Currently this code is here for DoT, which 12127 1.20 christos * has more complex requirements for zone 12128 1.20 christos * transfers compared to other stream 12129 1.20 christos * protocols. See RFC 9103 for details. 12130 1.20 christos */ 12131 1.20 christos switch (isc_nm_xfr_checkperm(handle)) { 12132 1.20 christos case ISC_R_SUCCESS: 12133 1.20 christos break; 12134 1.20 christos case ISC_R_DOTALPNERROR: 12135 1.20 christos query_error(client, DNS_R_NOALPN, 12136 1.20 christos __LINE__); 12137 1.20 christos return; 12138 1.20 christos default: 12139 1.20 christos query_error(client, DNS_R_REFUSED, 12140 1.20 christos __LINE__); 12141 1.20 christos return; 12142 1.20 christos } 12143 1.20 christos } 12144 1.1 christos ns_xfr_start(client, rdataset->type); 12145 1.1 christos return; 12146 1.1 christos case dns_rdatatype_maila: 12147 1.1 christos case dns_rdatatype_mailb: 12148 1.1 christos query_error(client, DNS_R_NOTIMP, __LINE__); 12149 1.1 christos return; 12150 1.1 christos case dns_rdatatype_tkey: 12151 1.9 christos result = dns_tkey_processquery( 12152 1.23 christos client->message, client->manager->sctx->tkeyctx, 12153 1.9 christos client->view->dynamickeys); 12154 1.9 christos if (result == ISC_R_SUCCESS) { 12155 1.1 christos query_send(client); 12156 1.9 christos } else { 12157 1.1 christos query_error(client, result, __LINE__); 12158 1.9 christos } 12159 1.1 christos return; 12160 1.1 christos default: /* TSIG, etc. */ 12161 1.1 christos query_error(client, DNS_R_FORMERR, __LINE__); 12162 1.1 christos return; 12163 1.1 christos } 12164 1.1 christos } 12165 1.1 christos 12166 1.1 christos /* 12167 1.1 christos * Turn on minimal response for (C)DNSKEY and (C)DS queries. 12168 1.1 christos */ 12169 1.22 christos if (dns_rdatatype_iskeymaterial(qtype) || qtype == dns_rdatatype_ds) { 12170 1.1 christos client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 12171 1.1 christos NS_QUERYATTR_NOADDITIONAL); 12172 1.11 christos } else if (qtype == dns_rdatatype_ns) { 12173 1.11 christos /* 12174 1.11 christos * Always turn on additional records for NS queries. 12175 1.11 christos */ 12176 1.11 christos client->query.attributes &= ~(NS_QUERYATTR_NOAUTHORITY | 12177 1.11 christos NS_QUERYATTR_NOADDITIONAL); 12178 1.1 christos } 12179 1.1 christos 12180 1.1 christos /* 12181 1.1 christos * Maybe turn on minimal responses for ANY queries. 12182 1.1 christos */ 12183 1.9 christos if (qtype == dns_rdatatype_any && client->view->minimal_any && 12184 1.16 christos !TCP(client)) 12185 1.16 christos { 12186 1.1 christos client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 12187 1.1 christos NS_QUERYATTR_NOADDITIONAL); 12188 1.9 christos } 12189 1.1 christos 12190 1.1 christos /* 12191 1.1 christos * Turn on minimal responses for EDNS/UDP bufsize 512 queries. 12192 1.1 christos */ 12193 1.1 christos if (client->ednsversion >= 0 && client->udpsize <= 512U && !TCP(client)) 12194 1.9 christos { 12195 1.1 christos client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | 12196 1.1 christos NS_QUERYATTR_NOADDITIONAL); 12197 1.9 christos } 12198 1.1 christos 12199 1.1 christos /* 12200 1.1 christos * If the client has requested that DNSSEC checking be disabled, 12201 1.1 christos * allow lookups to return pending data and instruct the resolver 12202 1.1 christos * to return data before validation has completed. 12203 1.1 christos * 12204 1.1 christos * We don't need to set DNS_DBFIND_PENDINGOK when validation is 12205 1.1 christos * disabled as there will be no pending data. 12206 1.1 christos */ 12207 1.3 christos if ((message->flags & DNS_MESSAGEFLAG_CD) != 0 || 12208 1.16 christos qtype == dns_rdatatype_rrsig) 12209 1.16 christos { 12210 1.1 christos client->query.dboptions |= DNS_DBFIND_PENDINGOK; 12211 1.1 christos client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE; 12212 1.9 christos } else if (!client->view->enablevalidation) { 12213 1.1 christos client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE; 12214 1.9 christos } 12215 1.1 christos 12216 1.3 christos if (client->view->qminimization) { 12217 1.3 christos client->query.fetchoptions |= DNS_FETCHOPT_QMINIMIZE | 12218 1.9 christos DNS_FETCHOPT_QMIN_SKIP_IP6A; 12219 1.3 christos if (client->view->qmin_strict) { 12220 1.3 christos client->query.fetchoptions |= DNS_FETCHOPT_QMIN_STRICT; 12221 1.3 christos } 12222 1.3 christos } 12223 1.3 christos 12224 1.1 christos /* 12225 1.1 christos * Allow glue NS records to be added to the authority section 12226 1.1 christos * if the answer is secure. 12227 1.1 christos */ 12228 1.3 christos if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) { 12229 1.1 christos client->query.attributes &= ~NS_QUERYATTR_SECURE; 12230 1.3 christos } 12231 1.1 christos 12232 1.1 christos /* 12233 1.1 christos * Set NS_CLIENTATTR_WANTAD if the client has set AD in the query. 12234 1.1 christos * This allows AD to be returned on queries without DO set. 12235 1.1 christos */ 12236 1.9 christos if ((message->flags & DNS_MESSAGEFLAG_AD) != 0) { 12237 1.1 christos client->attributes |= NS_CLIENTATTR_WANTAD; 12238 1.9 christos } 12239 1.1 christos 12240 1.1 christos /* 12241 1.1 christos * This is an ordinary query. 12242 1.1 christos */ 12243 1.3 christos result = dns_message_reply(message, true); 12244 1.1 christos if (result != ISC_R_SUCCESS) { 12245 1.1 christos query_next(client, result); 12246 1.1 christos return; 12247 1.1 christos } 12248 1.1 christos 12249 1.1 christos /* 12250 1.1 christos * Assume authoritative response until it is known to be 12251 1.1 christos * otherwise. 12252 1.1 christos * 12253 1.1 christos * If "-T noaa" has been set on the command line don't set 12254 1.1 christos * AA on authoritative answers. 12255 1.1 christos */ 12256 1.23 christos if ((client->manager->sctx->options & NS_SERVER_NOAA) == 0) { 12257 1.1 christos message->flags |= DNS_MESSAGEFLAG_AA; 12258 1.9 christos } 12259 1.1 christos 12260 1.1 christos /* 12261 1.1 christos * Set AD. We must clear it if we add non-validated data to a 12262 1.1 christos * response. 12263 1.1 christos */ 12264 1.9 christos if (WANTDNSSEC(client) || WANTAD(client)) { 12265 1.1 christos message->flags |= DNS_MESSAGEFLAG_AD; 12266 1.9 christos } 12267 1.1 christos 12268 1.24 christos /* 12269 1.24 christos * Start global outgoing query count. 12270 1.24 christos */ 12271 1.24 christos result = isc_counter_create(client->manager->mctx, 12272 1.24 christos client->view->max_queries, 12273 1.24 christos &client->query.qc); 12274 1.24 christos if (result != ISC_R_SUCCESS) { 12275 1.24 christos query_next(client, result); 12276 1.24 christos return; 12277 1.24 christos } 12278 1.24 christos 12279 1.23 christos query_setup(client, qtype); 12280 1.1 christos } 12281