1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 #include <inttypes.h>
15 #include <stdbool.h>
16
17 #include <isc/aes.h>
18 #include <isc/atomic.h>
19 #include <isc/formatcheck.h>
20 #include <isc/fuzz.h>
21 #include <isc/hmac.h>
22 #include <isc/mutex.h>
23 #include <isc/nonce.h>
24 #include <isc/once.h>
25 #include <isc/platform.h>
26 #include <isc/print.h>
27 #include <isc/random.h>
28 #include <isc/safe.h>
29 #include <isc/serial.h>
30 #include <isc/siphash.h>
31 #include <isc/stats.h>
32 #include <isc/stdio.h>
33 #include <isc/string.h>
34 #include <isc/task.h>
35 #include <isc/timer.h>
36 #include <isc/util.h>
37
38 #include <dns/adb.h>
39 #include <dns/badcache.h>
40 #include <dns/cache.h>
41 #include <dns/db.h>
42 #include <dns/dispatch.h>
43 #include <dns/dnstap.h>
44 #include <dns/edns.h>
45 #include <dns/events.h>
46 #include <dns/message.h>
47 #include <dns/peer.h>
48 #include <dns/rcode.h>
49 #include <dns/rdata.h>
50 #include <dns/rdataclass.h>
51 #include <dns/rdatalist.h>
52 #include <dns/rdataset.h>
53 #include <dns/resolver.h>
54 #include <dns/stats.h>
55 #include <dns/tsig.h>
56 #include <dns/view.h>
57 #include <dns/zone.h>
58
59 #include <ns/client.h>
60 #include <ns/interfacemgr.h>
61 #include <ns/log.h>
62 #include <ns/notify.h>
63 #include <ns/server.h>
64 #include <ns/stats.h>
65 #include <ns/update.h>
66
67 /***
68 *** Client
69 ***/
70
71 /*! \file
72 * Client Routines
73 *
74 * Important note!
75 *
76 * All client state changes, other than that from idle to listening, occur
77 * as a result of events. This guarantees serialization and avoids the
78 * need for locking.
79 *
80 * If a routine is ever created that allows someone other than the client's
81 * task to change the client, then the client will have to be locked.
82 */
83
84 #ifdef NS_CLIENT_TRACE
85 #define CTRACE(m) \
86 ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, \
87 ISC_LOG_DEBUG(3), "%s", (m))
88 #define MTRACE(m) \
89 isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, \
90 ISC_LOG_DEBUG(3), "clientmgr @%p: %s", manager, (m))
91 #else /* ifdef NS_CLIENT_TRACE */
92 #define CTRACE(m) ((void)(m))
93 #define MTRACE(m) ((void)(m))
94 #endif /* ifdef NS_CLIENT_TRACE */
95
96 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
97
98 #define COOKIE_SIZE 24U /* 8 + 4 + 4 + 8 */
99 #define ECS_SIZE 20U /* 2 + 1 + 1 + [0..16] */
100
101 #define WANTNSID(x) (((x)->attributes & NS_CLIENTATTR_WANTNSID) != 0)
102 #define WANTEXPIRE(x) (((x)->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0)
103 #define WANTPAD(x) (((x)->attributes & NS_CLIENTATTR_WANTPAD) != 0)
104 #define USEKEEPALIVE(x) (((x)->attributes & NS_CLIENTATTR_USEKEEPALIVE) != 0)
105
106 #define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
107 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
108
109 /*
110 * Enable ns_client_dropport() by default.
111 */
112 #ifndef NS_CLIENT_DROPPORT
113 #define NS_CLIENT_DROPPORT 1
114 #endif /* ifndef NS_CLIENT_DROPPORT */
115
116 #define CLIENT_NMCTXS_PERCPU 8
117 /*%<
118 * Number of 'mctx pools' for clients. (Should this be configurable?)
119 * When enabling threads, we use a pool of memory contexts shared by
120 * client objects, since concurrent access to a shared context would cause
121 * heavy contentions. The above constant is expected to be enough for
122 * completely avoiding contentions among threads for an authoritative-only
123 * server.
124 */
125
126 #define CLIENT_NTASKS_PERCPU 32
127 /*%<
128 * Number of tasks to be used by clients - those are used only when recursing
129 */
130
131 #if defined(_WIN32) && !defined(_WIN64)
132 LIBNS_EXTERNAL_DATA atomic_uint_fast32_t ns_client_requests =
133 ATOMIC_VAR_INIT(0);
134 #else /* if defined(_WIN32) && !defined(_WIN64) */
135 LIBNS_EXTERNAL_DATA atomic_uint_fast64_t ns_client_requests =
136 ATOMIC_VAR_INIT(0);
137 #endif /* if defined(_WIN32) && !defined(_WIN64) */
138
139 static void
140 clientmgr_attach(ns_clientmgr_t *source, ns_clientmgr_t **targetp);
141 static void
142 clientmgr_detach(ns_clientmgr_t **mp);
143 static void
144 clientmgr_destroy(ns_clientmgr_t *manager);
145 static void
146 ns_client_endrequest(ns_client_t *client);
147 static void
148 ns_client_dumpmessage(ns_client_t *client, const char *reason);
149 static void
150 compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
151 const unsigned char *secret, isc_buffer_t *buf);
152 static void
153 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp);
154 static void
155 get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp);
156
157 void
ns_client_recursing(ns_client_t * client)158 ns_client_recursing(ns_client_t *client) {
159 REQUIRE(NS_CLIENT_VALID(client));
160 REQUIRE(client->state == NS_CLIENTSTATE_WORKING);
161
162 LOCK(&client->manager->reclock);
163 client->state = NS_CLIENTSTATE_RECURSING;
164 ISC_LIST_APPEND(client->manager->recursing, client, rlink);
165 UNLOCK(&client->manager->reclock);
166 }
167
168 void
ns_client_killoldestquery(ns_client_t * client)169 ns_client_killoldestquery(ns_client_t *client) {
170 ns_client_t *oldest;
171 REQUIRE(NS_CLIENT_VALID(client));
172
173 LOCK(&client->manager->reclock);
174 oldest = ISC_LIST_HEAD(client->manager->recursing);
175 if (oldest != NULL) {
176 ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink);
177 ns_query_cancel(oldest);
178 ns_stats_increment(client->sctx->nsstats,
179 ns_statscounter_reclimitdropped);
180 }
181 UNLOCK(&client->manager->reclock);
182 }
183
184 void
ns_client_settimeout(ns_client_t * client,unsigned int seconds)185 ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
186 UNUSED(client);
187 UNUSED(seconds);
188 /* XXXWPK TODO use netmgr to set timeout */
189 }
190
191 static void
ns_client_endrequest(ns_client_t * client)192 ns_client_endrequest(ns_client_t *client) {
193 INSIST(client->nupdates == 0);
194 INSIST(client->state == NS_CLIENTSTATE_WORKING ||
195 client->state == NS_CLIENTSTATE_RECURSING);
196
197 CTRACE("endrequest");
198
199 if (client->state == NS_CLIENTSTATE_RECURSING) {
200 LOCK(&client->manager->reclock);
201 if (ISC_LINK_LINKED(client, rlink)) {
202 ISC_LIST_UNLINK(client->manager->recursing, client,
203 rlink);
204 }
205 UNLOCK(&client->manager->reclock);
206 }
207
208 if (client->cleanup != NULL) {
209 (client->cleanup)(client);
210 client->cleanup = NULL;
211 }
212
213 if (client->view != NULL) {
214 #ifdef ENABLE_AFL
215 if (client->sctx->fuzztype == isc_fuzz_resolver) {
216 dns_cache_clean(client->view->cache, INT_MAX);
217 dns_adb_flush(client->view->adb);
218 }
219 #endif /* ifdef ENABLE_AFL */
220 dns_view_detach(&client->view);
221 }
222 if (client->opt != NULL) {
223 INSIST(dns_rdataset_isassociated(client->opt));
224 dns_rdataset_disassociate(client->opt);
225 dns_message_puttemprdataset(client->message, &client->opt);
226 }
227
228 client->signer = NULL;
229 client->udpsize = 512;
230 client->extflags = 0;
231 client->ednsversion = -1;
232 dns_ecs_init(&client->ecs);
233 dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
234
235 /*
236 * Clean up from recursion - normally this would be done in
237 * fetch_callback(), but if we're shutting down and canceling then
238 * it might not have happened.
239 */
240 if (client->recursionquota != NULL) {
241 isc_quota_detach(&client->recursionquota);
242 if (client->query.prefetch == NULL) {
243 ns_stats_decrement(client->sctx->nsstats,
244 ns_statscounter_recursclients);
245 }
246 }
247
248 /*
249 * Clear all client attributes that are specific to the request
250 */
251 client->attributes = 0;
252 #ifdef ENABLE_AFL
253 if (client->sctx->fuzznotify != NULL &&
254 (client->sctx->fuzztype == isc_fuzz_client ||
255 client->sctx->fuzztype == isc_fuzz_tcpclient ||
256 client->sctx->fuzztype == isc_fuzz_resolver))
257 {
258 client->sctx->fuzznotify();
259 }
260 #endif /* ENABLE_AFL */
261 }
262
263 void
ns_client_drop(ns_client_t * client,isc_result_t result)264 ns_client_drop(ns_client_t *client, isc_result_t result) {
265 REQUIRE(NS_CLIENT_VALID(client));
266 REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
267 client->state == NS_CLIENTSTATE_RECURSING);
268
269 CTRACE("drop");
270 if (result != ISC_R_SUCCESS) {
271 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
272 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
273 "request failed: %s", isc_result_totext(result));
274 }
275 }
276
277 static void
client_senddone(isc_nmhandle_t * handle,isc_result_t result,void * cbarg)278 client_senddone(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
279 ns_client_t *client = cbarg;
280
281 REQUIRE(client->sendhandle == handle);
282
283 CTRACE("senddone");
284
285 /*
286 * Set sendhandle to NULL, but don't detach it immediately, in
287 * case we need to retry the send. If we do resend, then
288 * sendhandle will be reattached. Whether or not we resend,
289 * we will then detach the handle from *this* send by detaching
290 * 'handle' directly below.
291 */
292 client->sendhandle = NULL;
293
294 if (result != ISC_R_SUCCESS) {
295 if (!TCP_CLIENT(client) && result == ISC_R_MAXSIZE) {
296 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
297 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
298 "send exceeded maximum size: truncating");
299 client->query.attributes &= ~NS_QUERYATTR_ANSWERED;
300 client->rcode_override = dns_rcode_noerror;
301 ns_client_error(client, ISC_R_MAXSIZE);
302 } else {
303 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
304 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
305 "send failed: %s",
306 isc_result_totext(result));
307 }
308 }
309
310 isc_nmhandle_detach(&handle);
311 }
312
313 static void
client_allocsendbuf(ns_client_t * client,isc_buffer_t * buffer,unsigned char ** datap)314 client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
315 unsigned char **datap) {
316 unsigned char *data;
317 uint32_t bufsize;
318
319 REQUIRE(datap != NULL);
320
321 if (TCP_CLIENT(client)) {
322 INSIST(client->tcpbuf == NULL);
323 client->tcpbuf = isc_mem_get(client->mctx,
324 NS_CLIENT_TCP_BUFFER_SIZE);
325 data = client->tcpbuf;
326 isc_buffer_init(buffer, data, NS_CLIENT_TCP_BUFFER_SIZE);
327 } else {
328 data = client->sendbuf;
329 if ((client->attributes & NS_CLIENTATTR_HAVECOOKIE) == 0) {
330 if (client->view != NULL) {
331 bufsize = client->view->nocookieudp;
332 } else {
333 bufsize = 512;
334 }
335 } else {
336 bufsize = client->udpsize;
337 }
338 if (bufsize > client->udpsize) {
339 bufsize = client->udpsize;
340 }
341 if (bufsize > NS_CLIENT_SEND_BUFFER_SIZE) {
342 bufsize = NS_CLIENT_SEND_BUFFER_SIZE;
343 }
344 isc_buffer_init(buffer, data, bufsize);
345 }
346 *datap = data;
347 }
348
349 static void
client_sendpkg(ns_client_t * client,isc_buffer_t * buffer)350 client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
351 isc_region_t r;
352
353 REQUIRE(client->sendhandle == NULL);
354
355 isc_buffer_usedregion(buffer, &r);
356 isc_nmhandle_attach(client->handle, &client->sendhandle);
357 isc_nm_send(client->handle, &r, client_senddone, client);
358 }
359
360 void
ns_client_sendraw(ns_client_t * client,dns_message_t * message)361 ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
362 isc_result_t result;
363 unsigned char *data;
364 isc_buffer_t buffer;
365 isc_region_t r;
366 isc_region_t *mr;
367
368 REQUIRE(NS_CLIENT_VALID(client));
369
370 CTRACE("sendraw");
371
372 mr = dns_message_getrawmessage(message);
373 if (mr == NULL) {
374 result = ISC_R_UNEXPECTEDEND;
375 goto done;
376 }
377
378 client_allocsendbuf(client, &buffer, &data);
379
380 if (mr->length > isc_buffer_length(&buffer)) {
381 result = ISC_R_NOSPACE;
382 goto done;
383 }
384
385 /*
386 * Copy message to buffer and fixup id.
387 */
388 isc_buffer_availableregion(&buffer, &r);
389 result = isc_buffer_copyregion(&buffer, mr);
390 if (result != ISC_R_SUCCESS) {
391 goto done;
392 }
393 r.base[0] = (client->message->id >> 8) & 0xff;
394 r.base[1] = client->message->id & 0xff;
395
396 #ifdef HAVE_DNSTAP
397 if (client->view != NULL) {
398 bool tcp = TCP_CLIENT(client);
399 dns_dtmsgtype_t dtmsgtype;
400 if (client->message->opcode == dns_opcode_update) {
401 dtmsgtype = DNS_DTTYPE_UR;
402 } else if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
403 dtmsgtype = DNS_DTTYPE_CR;
404 } else {
405 dtmsgtype = DNS_DTTYPE_AR;
406 }
407 dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
408 &client->destsockaddr, tcp, NULL,
409 &client->requesttime, NULL, &buffer);
410 }
411 #endif
412
413 client_sendpkg(client, &buffer);
414
415 return;
416 done:
417 if (client->tcpbuf != NULL) {
418 isc_mem_put(client->mctx, client->tcpbuf,
419 NS_CLIENT_TCP_BUFFER_SIZE);
420 client->tcpbuf = NULL;
421 }
422
423 ns_client_drop(client, result);
424 }
425
426 void
ns_client_send(ns_client_t * client)427 ns_client_send(ns_client_t *client) {
428 isc_result_t result;
429 unsigned char *data;
430 isc_buffer_t buffer = { .magic = 0 };
431 isc_region_t r;
432 dns_compress_t cctx;
433 bool cleanup_cctx = false;
434 unsigned int render_opts;
435 unsigned int preferred_glue;
436 bool opt_included = false;
437 size_t respsize;
438 dns_aclenv_t *env;
439 #ifdef HAVE_DNSTAP
440 unsigned char zone[DNS_NAME_MAXWIRE];
441 dns_dtmsgtype_t dtmsgtype;
442 isc_region_t zr;
443 #endif /* HAVE_DNSTAP */
444
445 REQUIRE(NS_CLIENT_VALID(client));
446
447 if ((client->query.attributes & NS_QUERYATTR_ANSWERED) != 0) {
448 return;
449 }
450
451 /*
452 * XXXWPK TODO
453 * Delay the response according to the -T delay option
454 */
455
456 env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
457
458 CTRACE("send");
459
460 if (client->message->opcode == dns_opcode_query &&
461 (client->attributes & NS_CLIENTATTR_RA) != 0)
462 {
463 client->message->flags |= DNS_MESSAGEFLAG_RA;
464 }
465
466 if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) {
467 render_opts = 0;
468 } else {
469 render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
470 }
471
472 preferred_glue = 0;
473 if (client->view != NULL) {
474 if (client->view->preferred_glue == dns_rdatatype_a) {
475 preferred_glue = DNS_MESSAGERENDER_PREFER_A;
476 } else if (client->view->preferred_glue == dns_rdatatype_aaaa) {
477 preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
478 }
479 }
480 if (preferred_glue == 0) {
481 if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) {
482 preferred_glue = DNS_MESSAGERENDER_PREFER_A;
483 } else {
484 preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
485 }
486 }
487
488 /*
489 * Create an OPT for our reply.
490 */
491 if ((client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
492 result = ns_client_addopt(client, client->message,
493 &client->opt);
494 if (result != ISC_R_SUCCESS) {
495 goto cleanup;
496 }
497 }
498
499 client_allocsendbuf(client, &buffer, &data);
500
501 result = dns_compress_init(&cctx, -1, client->mctx);
502 if (result != ISC_R_SUCCESS) {
503 goto cleanup;
504 }
505 if (client->peeraddr_valid && client->view != NULL) {
506 isc_netaddr_t netaddr;
507 dns_name_t *name = NULL;
508
509 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
510 if (client->message->tsigkey != NULL) {
511 name = &client->message->tsigkey->name;
512 }
513
514 if (client->view->nocasecompress == NULL ||
515 !dns_acl_allowed(&netaddr, name,
516 client->view->nocasecompress, env))
517 {
518 dns_compress_setsensitive(&cctx, true);
519 }
520
521 if (!client->view->msgcompression) {
522 dns_compress_disable(&cctx);
523 }
524 }
525 cleanup_cctx = true;
526
527 result = dns_message_renderbegin(client->message, &cctx, &buffer);
528 if (result != ISC_R_SUCCESS) {
529 goto cleanup;
530 }
531
532 if (client->opt != NULL) {
533 result = dns_message_setopt(client->message, client->opt);
534 opt_included = true;
535 client->opt = NULL;
536 if (result != ISC_R_SUCCESS) {
537 goto cleanup;
538 }
539 }
540 result = dns_message_rendersection(client->message,
541 DNS_SECTION_QUESTION, 0);
542 if (result == ISC_R_NOSPACE) {
543 client->message->flags |= DNS_MESSAGEFLAG_TC;
544 goto renderend;
545 }
546 if (result != ISC_R_SUCCESS) {
547 goto cleanup;
548 }
549 /*
550 * Stop after the question if TC was set for rate limiting.
551 */
552 if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0) {
553 goto renderend;
554 }
555 result = dns_message_rendersection(client->message, DNS_SECTION_ANSWER,
556 DNS_MESSAGERENDER_PARTIAL |
557 render_opts);
558 if (result == ISC_R_NOSPACE) {
559 client->message->flags |= DNS_MESSAGEFLAG_TC;
560 goto renderend;
561 }
562 if (result != ISC_R_SUCCESS) {
563 goto cleanup;
564 }
565 result = dns_message_rendersection(
566 client->message, DNS_SECTION_AUTHORITY,
567 DNS_MESSAGERENDER_PARTIAL | render_opts);
568 if (result == ISC_R_NOSPACE) {
569 client->message->flags |= DNS_MESSAGEFLAG_TC;
570 goto renderend;
571 }
572 if (result != ISC_R_SUCCESS) {
573 goto cleanup;
574 }
575 result = dns_message_rendersection(client->message,
576 DNS_SECTION_ADDITIONAL,
577 preferred_glue | render_opts);
578 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) {
579 goto cleanup;
580 }
581 renderend:
582 result = dns_message_renderend(client->message);
583 if (result != ISC_R_SUCCESS) {
584 goto cleanup;
585 }
586
587 #ifdef HAVE_DNSTAP
588 memset(&zr, 0, sizeof(zr));
589 if (((client->message->flags & DNS_MESSAGEFLAG_AA) != 0) &&
590 (client->query.authzone != NULL))
591 {
592 isc_result_t eresult;
593 isc_buffer_t b;
594 dns_name_t *zo = dns_zone_getorigin(client->query.authzone);
595
596 isc_buffer_init(&b, zone, sizeof(zone));
597 dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE);
598 eresult = dns_name_towire(zo, &cctx, &b);
599 if (eresult == ISC_R_SUCCESS) {
600 isc_buffer_usedregion(&b, &zr);
601 }
602 }
603
604 if (client->message->opcode == dns_opcode_update) {
605 dtmsgtype = DNS_DTTYPE_UR;
606 } else if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
607 dtmsgtype = DNS_DTTYPE_CR;
608 } else {
609 dtmsgtype = DNS_DTTYPE_AR;
610 }
611 #endif /* HAVE_DNSTAP */
612
613 if (cleanup_cctx) {
614 dns_compress_invalidate(&cctx);
615 }
616
617 if (client->sendcb != NULL) {
618 client->sendcb(&buffer);
619 } else if (TCP_CLIENT(client)) {
620 isc_buffer_usedregion(&buffer, &r);
621 #ifdef HAVE_DNSTAP
622 if (client->view != NULL) {
623 dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
624 &client->destsockaddr, true, &zr,
625 &client->requesttime, NULL, &buffer);
626 }
627 #endif /* HAVE_DNSTAP */
628
629 respsize = isc_buffer_usedlength(&buffer);
630
631 client_sendpkg(client, &buffer);
632
633 switch (isc_sockaddr_pf(&client->peeraddr)) {
634 case AF_INET:
635 isc_stats_increment(client->sctx->tcpoutstats4,
636 ISC_MIN((int)respsize / 16, 256));
637 break;
638 case AF_INET6:
639 isc_stats_increment(client->sctx->tcpoutstats6,
640 ISC_MIN((int)respsize / 16, 256));
641 break;
642 default:
643 INSIST(0);
644 ISC_UNREACHABLE();
645 }
646 } else {
647 #ifdef HAVE_DNSTAP
648 /*
649 * Log dnstap data first, because client_sendpkg() may
650 * leave client->view set to NULL.
651 */
652 if (client->view != NULL) {
653 dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
654 &client->destsockaddr, false, &zr,
655 &client->requesttime, NULL, &buffer);
656 }
657 #endif /* HAVE_DNSTAP */
658
659 respsize = isc_buffer_usedlength(&buffer);
660
661 client_sendpkg(client, &buffer);
662
663 switch (isc_sockaddr_pf(&client->peeraddr)) {
664 case AF_INET:
665 isc_stats_increment(client->sctx->udpoutstats4,
666 ISC_MIN((int)respsize / 16, 256));
667 break;
668 case AF_INET6:
669 isc_stats_increment(client->sctx->udpoutstats6,
670 ISC_MIN((int)respsize / 16, 256));
671 break;
672 default:
673 INSIST(0);
674 ISC_UNREACHABLE();
675 }
676 }
677
678 /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
679 ns_stats_increment(client->sctx->nsstats, ns_statscounter_response);
680
681 dns_rcodestats_increment(client->sctx->rcodestats,
682 client->message->rcode);
683 if (opt_included) {
684 ns_stats_increment(client->sctx->nsstats,
685 ns_statscounter_edns0out);
686 }
687 if (client->message->tsigkey != NULL) {
688 ns_stats_increment(client->sctx->nsstats,
689 ns_statscounter_tsigout);
690 }
691 if (client->message->sig0key != NULL) {
692 ns_stats_increment(client->sctx->nsstats,
693 ns_statscounter_sig0out);
694 }
695 if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0) {
696 ns_stats_increment(client->sctx->nsstats,
697 ns_statscounter_truncatedresp);
698 }
699
700 client->query.attributes |= NS_QUERYATTR_ANSWERED;
701
702 return;
703
704 cleanup:
705 if (client->tcpbuf != NULL) {
706 isc_mem_put(client->mctx, client->tcpbuf,
707 NS_CLIENT_TCP_BUFFER_SIZE);
708 client->tcpbuf = NULL;
709 }
710
711 if (cleanup_cctx) {
712 dns_compress_invalidate(&cctx);
713 }
714 }
715
716 #if NS_CLIENT_DROPPORT
717 #define DROPPORT_NO 0
718 #define DROPPORT_REQUEST 1
719 #define DROPPORT_RESPONSE 2
720 /*%
721 * ns_client_dropport determines if certain requests / responses
722 * should be dropped based on the port number.
723 *
724 * Returns:
725 * \li 0: Don't drop.
726 * \li 1: Drop request.
727 * \li 2: Drop (error) response.
728 */
729 static int
ns_client_dropport(in_port_t port)730 ns_client_dropport(in_port_t port) {
731 switch (port) {
732 case 7: /* echo */
733 case 13: /* daytime */
734 case 19: /* chargen */
735 case 37: /* time */
736 return (DROPPORT_REQUEST);
737 case 464: /* kpasswd */
738 return (DROPPORT_RESPONSE);
739 }
740 return (DROPPORT_NO);
741 }
742 #endif /* if NS_CLIENT_DROPPORT */
743
744 void
ns_client_error(ns_client_t * client,isc_result_t result)745 ns_client_error(ns_client_t *client, isc_result_t result) {
746 dns_message_t *message = NULL;
747 dns_rcode_t rcode;
748 bool trunc = false;
749
750 REQUIRE(NS_CLIENT_VALID(client));
751
752 CTRACE("error");
753
754 message = client->message;
755
756 if (client->rcode_override == -1) {
757 rcode = dns_result_torcode(result);
758 } else {
759 rcode = (dns_rcode_t)(client->rcode_override & 0xfff);
760 }
761
762 if (result == ISC_R_MAXSIZE) {
763 trunc = true;
764 }
765
766 #if NS_CLIENT_DROPPORT
767 /*
768 * Don't send FORMERR to ports on the drop port list.
769 */
770 if (rcode == dns_rcode_formerr &&
771 ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
772 DROPPORT_NO)
773 {
774 char buf[64];
775 isc_buffer_t b;
776
777 isc_buffer_init(&b, buf, sizeof(buf) - 1);
778 if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS) {
779 isc_buffer_putstr(&b, "UNKNOWN RCODE");
780 }
781 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
782 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
783 "dropped error (%.*s) response: suspicious port",
784 (int)isc_buffer_usedlength(&b), buf);
785 ns_client_drop(client, ISC_R_SUCCESS);
786 return;
787 }
788 #endif /* if NS_CLIENT_DROPPORT */
789
790 /*
791 * Try to rate limit error responses.
792 */
793 if (client->view != NULL && client->view->rrl != NULL) {
794 bool wouldlog;
795 char log_buf[DNS_RRL_LOG_BUF_LEN];
796 dns_rrl_result_t rrl_result;
797 int loglevel;
798
799 if ((client->sctx->options & NS_SERVER_LOGQUERIES) != 0) {
800 loglevel = DNS_RRL_LOG_DROP;
801 } else {
802 loglevel = ISC_LOG_DEBUG(1);
803 }
804 wouldlog = isc_log_wouldlog(ns_lctx, loglevel);
805 rrl_result = dns_rrl(
806 client->view, &client->peeraddr, TCP_CLIENT(client),
807 dns_rdataclass_in, dns_rdatatype_none, NULL, result,
808 client->now, wouldlog, log_buf, sizeof(log_buf));
809 if (rrl_result != DNS_RRL_RESULT_OK) {
810 /*
811 * Log dropped errors in the query category
812 * so that they are not lost in silence.
813 * Starts of rate-limited bursts are logged in
814 * NS_LOGCATEGORY_RRL.
815 */
816 if (wouldlog) {
817 ns_client_log(client,
818 NS_LOGCATEGORY_QUERY_ERRORS,
819 NS_LOGMODULE_CLIENT, loglevel,
820 "%s", log_buf);
821 }
822 /*
823 * Some error responses cannot be 'slipped',
824 * so don't try to slip any error responses.
825 */
826 if (!client->view->rrl->log_only) {
827 ns_stats_increment(client->sctx->nsstats,
828 ns_statscounter_ratedropped);
829 ns_stats_increment(client->sctx->nsstats,
830 ns_statscounter_dropped);
831 ns_client_drop(client, DNS_R_DROP);
832 return;
833 }
834 }
835 }
836
837 /*
838 * Message may be an in-progress reply that we had trouble
839 * with, in which case QR will be set. We need to clear QR before
840 * calling dns_message_reply() to avoid triggering an assertion.
841 */
842 message->flags &= ~DNS_MESSAGEFLAG_QR;
843 /*
844 * AA and AD shouldn't be set.
845 */
846 message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
847 result = dns_message_reply(message, true);
848 if (result != ISC_R_SUCCESS) {
849 /*
850 * It could be that we've got a query with a good header,
851 * but a bad question section, so we try again with
852 * want_question_section set to false.
853 */
854 result = dns_message_reply(message, false);
855 if (result != ISC_R_SUCCESS) {
856 ns_client_drop(client, result);
857 return;
858 }
859 }
860
861 message->rcode = rcode;
862 if (trunc) {
863 message->flags |= DNS_MESSAGEFLAG_TC;
864 }
865
866 if (rcode == dns_rcode_formerr) {
867 /*
868 * FORMERR loop avoidance: If we sent a FORMERR message
869 * with the same ID to the same client less than two
870 * seconds ago, assume that we are in an infinite error
871 * packet dialog with a server for some protocol whose
872 * error responses look enough like DNS queries to
873 * elicit a FORMERR response. Drop a packet to break
874 * the loop.
875 */
876 if (isc_sockaddr_equal(&client->peeraddr,
877 &client->formerrcache.addr) &&
878 message->id == client->formerrcache.id &&
879 (isc_time_seconds(&client->requesttime) -
880 client->formerrcache.time) < 2)
881 {
882 /* Drop packet. */
883 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
884 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
885 "possible error packet loop, "
886 "FORMERR dropped");
887 ns_client_drop(client, result);
888 return;
889 }
890 client->formerrcache.addr = client->peeraddr;
891 client->formerrcache.time =
892 isc_time_seconds(&client->requesttime);
893 client->formerrcache.id = message->id;
894 } else if (rcode == dns_rcode_servfail && client->query.qname != NULL &&
895 client->view != NULL && client->view->fail_ttl != 0 &&
896 ((client->attributes & NS_CLIENTATTR_NOSETFC) == 0))
897 {
898 /*
899 * SERVFAIL caching: store qname/qtype of failed queries
900 */
901 isc_time_t expire;
902 isc_interval_t i;
903 uint32_t flags = 0;
904
905 if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) {
906 flags = NS_FAILCACHE_CD;
907 }
908
909 isc_interval_set(&i, client->view->fail_ttl, 0);
910 result = isc_time_nowplusinterval(&expire, &i);
911 if (result == ISC_R_SUCCESS) {
912 dns_badcache_add(
913 client->view->failcache, client->query.qname,
914 client->query.qtype, true, flags, &expire);
915 }
916 }
917
918 ns_client_send(client);
919 }
920
921 isc_result_t
ns_client_addopt(ns_client_t * client,dns_message_t * message,dns_rdataset_t ** opt)922 ns_client_addopt(ns_client_t *client, dns_message_t *message,
923 dns_rdataset_t **opt) {
924 unsigned char ecs[ECS_SIZE];
925 char nsid[BUFSIZ], *nsidp;
926 unsigned char cookie[COOKIE_SIZE];
927 isc_result_t result;
928 dns_view_t *view;
929 dns_resolver_t *resolver;
930 uint16_t udpsize;
931 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
932 int count = 0;
933 unsigned int flags;
934 unsigned char expire[4];
935 unsigned char advtimo[2];
936 dns_aclenv_t *env;
937
938 REQUIRE(NS_CLIENT_VALID(client));
939 REQUIRE(opt != NULL && *opt == NULL);
940 REQUIRE(message != NULL);
941
942 env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
943 view = client->view;
944 resolver = (view != NULL) ? view->resolver : NULL;
945 if (resolver != NULL) {
946 udpsize = dns_resolver_getudpsize(resolver);
947 } else {
948 udpsize = client->sctx->udpsize;
949 }
950
951 flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
952
953 /* Set EDNS options if applicable */
954 if (WANTNSID(client)) {
955 if (client->sctx->server_id != NULL) {
956 nsidp = client->sctx->server_id;
957 } else if (client->sctx->gethostname != NULL) {
958 result = client->sctx->gethostname(nsid, sizeof(nsid));
959 if (result != ISC_R_SUCCESS) {
960 goto no_nsid;
961 }
962 nsidp = nsid;
963 } else {
964 goto no_nsid;
965 }
966
967 INSIST(count < DNS_EDNSOPTIONS);
968 ednsopts[count].code = DNS_OPT_NSID;
969 ednsopts[count].length = (uint16_t)strlen(nsidp);
970 ednsopts[count].value = (unsigned char *)nsidp;
971 count++;
972 }
973 no_nsid:
974 if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0) {
975 isc_buffer_t buf;
976 isc_stdtime_t now;
977 uint32_t nonce;
978
979 isc_buffer_init(&buf, cookie, sizeof(cookie));
980 isc_stdtime_get(&now);
981
982 isc_random_buf(&nonce, sizeof(nonce));
983
984 compute_cookie(client, now, nonce, client->sctx->secret, &buf);
985
986 INSIST(count < DNS_EDNSOPTIONS);
987 ednsopts[count].code = DNS_OPT_COOKIE;
988 ednsopts[count].length = COOKIE_SIZE;
989 ednsopts[count].value = cookie;
990 count++;
991 }
992 if ((client->attributes & NS_CLIENTATTR_HAVEEXPIRE) != 0) {
993 isc_buffer_t buf;
994
995 INSIST(count < DNS_EDNSOPTIONS);
996
997 isc_buffer_init(&buf, expire, sizeof(expire));
998 isc_buffer_putuint32(&buf, client->expire);
999 ednsopts[count].code = DNS_OPT_EXPIRE;
1000 ednsopts[count].length = 4;
1001 ednsopts[count].value = expire;
1002 count++;
1003 }
1004 if (((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) &&
1005 (client->ecs.addr.family == AF_INET ||
1006 client->ecs.addr.family == AF_INET6 ||
1007 client->ecs.addr.family == AF_UNSPEC))
1008 {
1009 isc_buffer_t buf;
1010 uint8_t addr[16];
1011 uint32_t plen, addrl;
1012 uint16_t family = 0;
1013
1014 /* Add CLIENT-SUBNET option. */
1015
1016 plen = client->ecs.source;
1017
1018 /* Round up prefix len to a multiple of 8 */
1019 addrl = (plen + 7) / 8;
1020
1021 switch (client->ecs.addr.family) {
1022 case AF_UNSPEC:
1023 INSIST(plen == 0);
1024 family = 0;
1025 break;
1026 case AF_INET:
1027 INSIST(plen <= 32);
1028 family = 1;
1029 memmove(addr, &client->ecs.addr.type, addrl);
1030 break;
1031 case AF_INET6:
1032 INSIST(plen <= 128);
1033 family = 2;
1034 memmove(addr, &client->ecs.addr.type, addrl);
1035 break;
1036 default:
1037 INSIST(0);
1038 ISC_UNREACHABLE();
1039 }
1040
1041 isc_buffer_init(&buf, ecs, sizeof(ecs));
1042 /* family */
1043 isc_buffer_putuint16(&buf, family);
1044 /* source prefix-length */
1045 isc_buffer_putuint8(&buf, client->ecs.source);
1046 /* scope prefix-length */
1047 isc_buffer_putuint8(&buf, client->ecs.scope);
1048
1049 /* address */
1050 if (addrl > 0) {
1051 /* Mask off last address byte */
1052 if ((plen % 8) != 0) {
1053 addr[addrl - 1] &= ~0U << (8 - (plen % 8));
1054 }
1055 isc_buffer_putmem(&buf, addr, (unsigned)addrl);
1056 }
1057
1058 ednsopts[count].code = DNS_OPT_CLIENT_SUBNET;
1059 ednsopts[count].length = addrl + 4;
1060 ednsopts[count].value = ecs;
1061 count++;
1062 }
1063 if (TCP_CLIENT(client) && USEKEEPALIVE(client)) {
1064 isc_buffer_t buf;
1065 uint32_t adv;
1066
1067 INSIST(count < DNS_EDNSOPTIONS);
1068
1069 isc_nm_gettimeouts(isc_nmhandle_netmgr(client->handle), NULL,
1070 NULL, NULL, &adv);
1071 adv /= 100; /* units of 100 milliseconds */
1072 isc_buffer_init(&buf, advtimo, sizeof(advtimo));
1073 isc_buffer_putuint16(&buf, (uint16_t)adv);
1074 ednsopts[count].code = DNS_OPT_TCP_KEEPALIVE;
1075 ednsopts[count].length = 2;
1076 ednsopts[count].value = advtimo;
1077 count++;
1078 }
1079
1080 /* Padding must be added last */
1081 if ((view != NULL) && (view->padding > 0) && WANTPAD(client) &&
1082 (TCP_CLIENT(client) ||
1083 ((client->attributes & NS_CLIENTATTR_HAVECOOKIE) != 0)))
1084 {
1085 isc_netaddr_t netaddr;
1086 int match;
1087
1088 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1089 result = dns_acl_match(&netaddr, NULL, view->pad_acl, env,
1090 &match, NULL);
1091 if (result == ISC_R_SUCCESS && match > 0) {
1092 INSIST(count < DNS_EDNSOPTIONS);
1093
1094 ednsopts[count].code = DNS_OPT_PAD;
1095 ednsopts[count].length = 0;
1096 ednsopts[count].value = NULL;
1097 count++;
1098
1099 dns_message_setpadding(message, view->padding);
1100 }
1101 }
1102
1103 result = dns_message_buildopt(message, opt, 0, udpsize, flags, ednsopts,
1104 count);
1105 return (result);
1106 }
1107
1108 static void
compute_cookie(ns_client_t * client,uint32_t when,uint32_t nonce,const unsigned char * secret,isc_buffer_t * buf)1109 compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
1110 const unsigned char *secret, isc_buffer_t *buf) {
1111 unsigned char digest[ISC_MAX_MD_SIZE] ISC_NONSTRING = { 0 };
1112 STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_SIPHASH24_TAG_LENGTH, "You need "
1113 "to "
1114 "increase "
1115 "the digest "
1116 "buffer.");
1117 STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_AES_BLOCK_LENGTH, "You need to "
1118 "increase the "
1119 "digest "
1120 "buffer.");
1121
1122 switch (client->sctx->cookiealg) {
1123 case ns_cookiealg_siphash24: {
1124 unsigned char input[16 + 16] ISC_NONSTRING = { 0 };
1125 size_t inputlen = 0;
1126 isc_netaddr_t netaddr;
1127 unsigned char *cp;
1128
1129 cp = isc_buffer_used(buf);
1130 isc_buffer_putmem(buf, client->cookie, 8);
1131 isc_buffer_putuint8(buf, NS_COOKIE_VERSION_1);
1132 isc_buffer_putuint24(buf, 0); /* Reserved */
1133 isc_buffer_putuint32(buf, when);
1134
1135 memmove(input, cp, 16);
1136
1137 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1138 switch (netaddr.family) {
1139 case AF_INET:
1140 cp = (unsigned char *)&netaddr.type.in;
1141 memmove(input + 16, cp, 4);
1142 inputlen = 20;
1143 break;
1144 case AF_INET6:
1145 cp = (unsigned char *)&netaddr.type.in6;
1146 memmove(input + 16, cp, 16);
1147 inputlen = 32;
1148 break;
1149 default:
1150 INSIST(0);
1151 ISC_UNREACHABLE();
1152 }
1153
1154 isc_siphash24(secret, input, inputlen, digest);
1155 isc_buffer_putmem(buf, digest, 8);
1156 break;
1157 }
1158 case ns_cookiealg_aes: {
1159 unsigned char input[4 + 4 + 16] ISC_NONSTRING = { 0 };
1160 isc_netaddr_t netaddr;
1161 unsigned char *cp;
1162 unsigned int i;
1163
1164 cp = isc_buffer_used(buf);
1165 isc_buffer_putmem(buf, client->cookie, 8);
1166 isc_buffer_putuint32(buf, nonce);
1167 isc_buffer_putuint32(buf, when);
1168 memmove(input, cp, 16);
1169 isc_aes128_crypt(secret, input, digest);
1170 for (i = 0; i < 8; i++) {
1171 input[i] = digest[i] ^ digest[i + 8];
1172 }
1173 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1174 switch (netaddr.family) {
1175 case AF_INET:
1176 cp = (unsigned char *)&netaddr.type.in;
1177 memmove(input + 8, cp, 4);
1178 memset(input + 12, 0, 4);
1179 isc_aes128_crypt(secret, input, digest);
1180 break;
1181 case AF_INET6:
1182 cp = (unsigned char *)&netaddr.type.in6;
1183 memmove(input + 8, cp, 16);
1184 isc_aes128_crypt(secret, input, digest);
1185 for (i = 0; i < 8; i++) {
1186 input[i + 8] = digest[i] ^ digest[i + 8];
1187 }
1188 isc_aes128_crypt(client->sctx->secret, input + 8,
1189 digest);
1190 break;
1191 default:
1192 INSIST(0);
1193 ISC_UNREACHABLE();
1194 }
1195 for (i = 0; i < 8; i++) {
1196 digest[i] ^= digest[i + 8];
1197 }
1198 isc_buffer_putmem(buf, digest, 8);
1199 break;
1200 }
1201
1202 default:
1203 INSIST(0);
1204 ISC_UNREACHABLE();
1205 }
1206 }
1207
1208 static void
process_cookie(ns_client_t * client,isc_buffer_t * buf,size_t optlen)1209 process_cookie(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
1210 ns_altsecret_t *altsecret;
1211 unsigned char dbuf[COOKIE_SIZE];
1212 unsigned char *old;
1213 isc_stdtime_t now;
1214 uint32_t when;
1215 uint32_t nonce;
1216 isc_buffer_t db;
1217
1218 /*
1219 * If we have already seen a cookie option skip this cookie option.
1220 */
1221 if ((!client->sctx->answercookie) ||
1222 (client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0)
1223 {
1224 isc_buffer_forward(buf, (unsigned int)optlen);
1225 return;
1226 }
1227
1228 client->attributes |= NS_CLIENTATTR_WANTCOOKIE;
1229
1230 ns_stats_increment(client->sctx->nsstats, ns_statscounter_cookiein);
1231
1232 if (optlen != COOKIE_SIZE) {
1233 /*
1234 * Not our token.
1235 */
1236 INSIST(optlen >= 8U);
1237 memmove(client->cookie, isc_buffer_current(buf), 8);
1238 isc_buffer_forward(buf, (unsigned int)optlen);
1239
1240 if (optlen == 8U) {
1241 ns_stats_increment(client->sctx->nsstats,
1242 ns_statscounter_cookienew);
1243 } else {
1244 ns_stats_increment(client->sctx->nsstats,
1245 ns_statscounter_cookiebadsize);
1246 }
1247 return;
1248 }
1249
1250 /*
1251 * Process all of the incoming buffer.
1252 */
1253 old = isc_buffer_current(buf);
1254 memmove(client->cookie, old, 8);
1255 isc_buffer_forward(buf, 8);
1256 nonce = isc_buffer_getuint32(buf);
1257 when = isc_buffer_getuint32(buf);
1258 isc_buffer_forward(buf, 8);
1259
1260 /*
1261 * Allow for a 5 minute clock skew between servers sharing a secret.
1262 * Only accept COOKIE if we have talked to the client in the last hour.
1263 */
1264 isc_stdtime_get(&now);
1265 if (isc_serial_gt(when, (now + 300)) || /* In the future. */
1266 isc_serial_lt(when, (now - 3600)))
1267 { /* In the past. */
1268 ns_stats_increment(client->sctx->nsstats,
1269 ns_statscounter_cookiebadtime);
1270 return;
1271 }
1272
1273 isc_buffer_init(&db, dbuf, sizeof(dbuf));
1274 compute_cookie(client, when, nonce, client->sctx->secret, &db);
1275
1276 if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
1277 ns_stats_increment(client->sctx->nsstats,
1278 ns_statscounter_cookiematch);
1279 client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
1280 return;
1281 }
1282
1283 for (altsecret = ISC_LIST_HEAD(client->sctx->altsecrets);
1284 altsecret != NULL; altsecret = ISC_LIST_NEXT(altsecret, link))
1285 {
1286 isc_buffer_init(&db, dbuf, sizeof(dbuf));
1287 compute_cookie(client, when, nonce, altsecret->secret, &db);
1288 if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
1289 ns_stats_increment(client->sctx->nsstats,
1290 ns_statscounter_cookiematch);
1291 client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
1292 return;
1293 }
1294 }
1295
1296 ns_stats_increment(client->sctx->nsstats,
1297 ns_statscounter_cookienomatch);
1298 }
1299
1300 static isc_result_t
process_ecs(ns_client_t * client,isc_buffer_t * buf,size_t optlen)1301 process_ecs(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
1302 uint16_t family;
1303 uint8_t addrlen, addrbytes, scope, *paddr;
1304 isc_netaddr_t caddr;
1305
1306 /*
1307 * If we have already seen a ECS option skip this ECS option.
1308 */
1309 if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
1310 isc_buffer_forward(buf, (unsigned int)optlen);
1311 return (ISC_R_SUCCESS);
1312 }
1313
1314 /*
1315 * XXXMUKS: Is there any need to repeat these checks here
1316 * (except query's scope length) when they are done in the OPT
1317 * RDATA fromwire code?
1318 */
1319
1320 if (optlen < 4U) {
1321 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1322 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1323 "EDNS client-subnet option too short");
1324 return (DNS_R_FORMERR);
1325 }
1326
1327 family = isc_buffer_getuint16(buf);
1328 addrlen = isc_buffer_getuint8(buf);
1329 scope = isc_buffer_getuint8(buf);
1330 optlen -= 4;
1331
1332 if (scope != 0U) {
1333 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1334 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1335 "EDNS client-subnet option: invalid scope");
1336 return (DNS_R_OPTERR);
1337 }
1338
1339 memset(&caddr, 0, sizeof(caddr));
1340 switch (family) {
1341 case 0:
1342 /*
1343 * XXXMUKS: In queries, if FAMILY is set to 0, SOURCE
1344 * PREFIX-LENGTH must be 0 and ADDRESS should not be
1345 * present as the address and prefix lengths don't make
1346 * sense because the family is unknown.
1347 */
1348 if (addrlen != 0U) {
1349 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1350 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1351 "EDNS client-subnet option: invalid "
1352 "address length (%u) for FAMILY=0",
1353 addrlen);
1354 return (DNS_R_OPTERR);
1355 }
1356 caddr.family = AF_UNSPEC;
1357 break;
1358 case 1:
1359 if (addrlen > 32U) {
1360 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1361 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1362 "EDNS client-subnet option: invalid "
1363 "address length (%u) for IPv4",
1364 addrlen);
1365 return (DNS_R_OPTERR);
1366 }
1367 caddr.family = AF_INET;
1368 break;
1369 case 2:
1370 if (addrlen > 128U) {
1371 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1372 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1373 "EDNS client-subnet option: invalid "
1374 "address length (%u) for IPv6",
1375 addrlen);
1376 return (DNS_R_OPTERR);
1377 }
1378 caddr.family = AF_INET6;
1379 break;
1380 default:
1381 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1382 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1383 "EDNS client-subnet option: invalid family");
1384 return (DNS_R_OPTERR);
1385 }
1386
1387 addrbytes = (addrlen + 7) / 8;
1388 if (isc_buffer_remaininglength(buf) < addrbytes) {
1389 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1390 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1391 "EDNS client-subnet option: address too short");
1392 return (DNS_R_OPTERR);
1393 }
1394
1395 paddr = (uint8_t *)&caddr.type;
1396 if (addrbytes != 0U) {
1397 memmove(paddr, isc_buffer_current(buf), addrbytes);
1398 isc_buffer_forward(buf, addrbytes);
1399 optlen -= addrbytes;
1400
1401 if ((addrlen % 8) != 0) {
1402 uint8_t bits = ~0U << (8 - (addrlen % 8));
1403 bits &= paddr[addrbytes - 1];
1404 if (bits != paddr[addrbytes - 1]) {
1405 return (DNS_R_OPTERR);
1406 }
1407 }
1408 }
1409
1410 memmove(&client->ecs.addr, &caddr, sizeof(caddr));
1411 client->ecs.source = addrlen;
1412 client->ecs.scope = 0;
1413 client->attributes |= NS_CLIENTATTR_HAVEECS;
1414
1415 isc_buffer_forward(buf, (unsigned int)optlen);
1416 return (ISC_R_SUCCESS);
1417 }
1418
1419 static isc_result_t
process_keytag(ns_client_t * client,isc_buffer_t * buf,size_t optlen)1420 process_keytag(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
1421 if (optlen == 0 || (optlen % 2) != 0) {
1422 isc_buffer_forward(buf, (unsigned int)optlen);
1423 return (DNS_R_OPTERR);
1424 }
1425
1426 /* Silently drop additional keytag options. */
1427 if (client->keytag != NULL) {
1428 isc_buffer_forward(buf, (unsigned int)optlen);
1429 return (ISC_R_SUCCESS);
1430 }
1431
1432 client->keytag = isc_mem_get(client->mctx, optlen);
1433 {
1434 client->keytag_len = (uint16_t)optlen;
1435 memmove(client->keytag, isc_buffer_current(buf), optlen);
1436 }
1437 isc_buffer_forward(buf, (unsigned int)optlen);
1438 return (ISC_R_SUCCESS);
1439 }
1440
1441 static isc_result_t
process_opt(ns_client_t * client,dns_rdataset_t * opt)1442 process_opt(ns_client_t *client, dns_rdataset_t *opt) {
1443 dns_rdata_t rdata;
1444 isc_buffer_t optbuf;
1445 isc_result_t result;
1446 uint16_t optcode;
1447 uint16_t optlen;
1448
1449 /*
1450 * Set the client's UDP buffer size.
1451 */
1452 client->udpsize = opt->rdclass;
1453
1454 /*
1455 * If the requested UDP buffer size is less than 512,
1456 * ignore it and use 512.
1457 */
1458 if (client->udpsize < 512) {
1459 client->udpsize = 512;
1460 }
1461
1462 /*
1463 * Get the flags out of the OPT record.
1464 */
1465 client->extflags = (uint16_t)(opt->ttl & 0xFFFF);
1466
1467 /*
1468 * Do we understand this version of EDNS?
1469 *
1470 * XXXRTH need library support for this!
1471 */
1472 client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1473 if (client->ednsversion > DNS_EDNS_VERSION) {
1474 ns_stats_increment(client->sctx->nsstats,
1475 ns_statscounter_badednsver);
1476 result = ns_client_addopt(client, client->message,
1477 &client->opt);
1478 if (result == ISC_R_SUCCESS) {
1479 result = DNS_R_BADVERS;
1480 }
1481 ns_client_error(client, result);
1482 return (result);
1483 }
1484
1485 /* Check for NSID request */
1486 result = dns_rdataset_first(opt);
1487 if (result == ISC_R_SUCCESS) {
1488 dns_rdata_init(&rdata);
1489 dns_rdataset_current(opt, &rdata);
1490 isc_buffer_init(&optbuf, rdata.data, rdata.length);
1491 isc_buffer_add(&optbuf, rdata.length);
1492 while (isc_buffer_remaininglength(&optbuf) >= 4) {
1493 optcode = isc_buffer_getuint16(&optbuf);
1494 optlen = isc_buffer_getuint16(&optbuf);
1495 switch (optcode) {
1496 case DNS_OPT_NSID:
1497 if (!WANTNSID(client)) {
1498 ns_stats_increment(
1499 client->sctx->nsstats,
1500 ns_statscounter_nsidopt);
1501 }
1502 client->attributes |= NS_CLIENTATTR_WANTNSID;
1503 isc_buffer_forward(&optbuf, optlen);
1504 break;
1505 case DNS_OPT_COOKIE:
1506 process_cookie(client, &optbuf, optlen);
1507 break;
1508 case DNS_OPT_EXPIRE:
1509 if (!WANTEXPIRE(client)) {
1510 ns_stats_increment(
1511 client->sctx->nsstats,
1512 ns_statscounter_expireopt);
1513 }
1514 client->attributes |= NS_CLIENTATTR_WANTEXPIRE;
1515 isc_buffer_forward(&optbuf, optlen);
1516 break;
1517 case DNS_OPT_CLIENT_SUBNET:
1518 result = process_ecs(client, &optbuf, optlen);
1519 if (result != ISC_R_SUCCESS) {
1520 ns_client_error(client, result);
1521 return (result);
1522 }
1523 ns_stats_increment(client->sctx->nsstats,
1524 ns_statscounter_ecsopt);
1525 break;
1526 case DNS_OPT_TCP_KEEPALIVE:
1527 if (!USEKEEPALIVE(client)) {
1528 ns_stats_increment(
1529 client->sctx->nsstats,
1530 ns_statscounter_keepaliveopt);
1531 }
1532 client->attributes |=
1533 NS_CLIENTATTR_USEKEEPALIVE;
1534 isc_nmhandle_keepalive(client->handle, true);
1535 isc_buffer_forward(&optbuf, optlen);
1536 break;
1537 case DNS_OPT_PAD:
1538 client->attributes |= NS_CLIENTATTR_WANTPAD;
1539 ns_stats_increment(client->sctx->nsstats,
1540 ns_statscounter_padopt);
1541 isc_buffer_forward(&optbuf, optlen);
1542 break;
1543 case DNS_OPT_KEY_TAG:
1544 result = process_keytag(client, &optbuf,
1545 optlen);
1546 if (result != ISC_R_SUCCESS) {
1547 ns_client_error(client, result);
1548 return (result);
1549 }
1550 ns_stats_increment(client->sctx->nsstats,
1551 ns_statscounter_keytagopt);
1552 break;
1553 default:
1554 ns_stats_increment(client->sctx->nsstats,
1555 ns_statscounter_otheropt);
1556 isc_buffer_forward(&optbuf, optlen);
1557 break;
1558 }
1559 }
1560 }
1561
1562 ns_stats_increment(client->sctx->nsstats, ns_statscounter_edns0in);
1563 client->attributes |= NS_CLIENTATTR_WANTOPT;
1564
1565 return (result);
1566 }
1567
1568 void
ns__client_reset_cb(void * client0)1569 ns__client_reset_cb(void *client0) {
1570 ns_client_t *client = client0;
1571
1572 ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1573 ISC_LOG_DEBUG(3), "reset client");
1574
1575 /*
1576 * We never started processing this client, possible if we're
1577 * shutting down, just exit.
1578 */
1579 if (client->state == NS_CLIENTSTATE_READY) {
1580 return;
1581 }
1582
1583 ns_client_endrequest(client);
1584 if (client->tcpbuf != NULL) {
1585 isc_mem_put(client->mctx, client->tcpbuf,
1586 NS_CLIENT_TCP_BUFFER_SIZE);
1587 }
1588
1589 if (client->keytag != NULL) {
1590 isc_mem_put(client->mctx, client->keytag, client->keytag_len);
1591 client->keytag_len = 0;
1592 }
1593
1594 client->state = NS_CLIENTSTATE_READY;
1595 INSIST(client->recursionquota == NULL);
1596 }
1597
1598 void
ns__client_put_cb(void * client0)1599 ns__client_put_cb(void *client0) {
1600 ns_client_t *client = client0;
1601
1602 ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1603 ISC_LOG_DEBUG(3), "freeing client");
1604
1605 /*
1606 * Call this first because it requires a valid client.
1607 */
1608 ns_query_free(client);
1609
1610 client->magic = 0;
1611 client->shuttingdown = true;
1612
1613 if (client->manager != NULL) {
1614 clientmgr_detach(&client->manager);
1615 }
1616
1617 isc_mem_put(client->mctx, client->sendbuf, NS_CLIENT_SEND_BUFFER_SIZE);
1618 if (client->opt != NULL) {
1619 INSIST(dns_rdataset_isassociated(client->opt));
1620 dns_rdataset_disassociate(client->opt);
1621 dns_message_puttemprdataset(client->message, &client->opt);
1622 }
1623
1624 dns_message_detach(&client->message);
1625
1626 /*
1627 * Detaching the task must be done after unlinking from
1628 * the manager's lists because the manager accesses
1629 * client->task.
1630 */
1631 if (client->task != NULL) {
1632 isc_task_detach(&client->task);
1633 }
1634
1635 /*
1636 * Destroy the fetchlock mutex that was created in
1637 * ns_query_init().
1638 */
1639 isc_mutex_destroy(&client->query.fetchlock);
1640
1641 if (client->sctx != NULL) {
1642 ns_server_detach(&client->sctx);
1643 }
1644
1645 if (client->mctx != NULL) {
1646 isc_mem_detach(&client->mctx);
1647 }
1648 }
1649
1650 /*
1651 * Handle an incoming request event from the socket (UDP case)
1652 * or tcpmsg (TCP case).
1653 */
1654 void
ns__client_request(isc_nmhandle_t * handle,isc_result_t eresult,isc_region_t * region,void * arg)1655 ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
1656 isc_region_t *region, void *arg) {
1657 ns_client_t *client = NULL;
1658 isc_result_t result;
1659 isc_result_t sigresult = ISC_R_SUCCESS;
1660 isc_buffer_t *buffer = NULL;
1661 isc_buffer_t tbuffer;
1662 dns_rdataset_t *opt = NULL;
1663 const dns_name_t *signame = NULL;
1664 bool ra; /* Recursion available. */
1665 isc_netaddr_t netaddr;
1666 int match;
1667 dns_messageid_t id;
1668 unsigned int flags;
1669 bool notimp;
1670 size_t reqsize;
1671 dns_aclenv_t *env = NULL;
1672 #ifdef HAVE_DNSTAP
1673 dns_dtmsgtype_t dtmsgtype;
1674 #endif /* ifdef HAVE_DNSTAP */
1675
1676 if (eresult != ISC_R_SUCCESS) {
1677 return;
1678 }
1679
1680 client = isc_nmhandle_getdata(handle);
1681 if (client == NULL) {
1682 ns_interface_t *ifp = (ns_interface_t *)arg;
1683
1684 INSIST(VALID_MANAGER(ifp->clientmgr));
1685
1686 client = isc_nmhandle_getextra(handle);
1687
1688 result = ns__client_setup(client, ifp->clientmgr, true);
1689 if (result != ISC_R_SUCCESS) {
1690 return;
1691 }
1692
1693 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1694 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1695 "allocate new client");
1696 } else {
1697 result = ns__client_setup(client, NULL, false);
1698 if (result != ISC_R_SUCCESS) {
1699 return;
1700 }
1701 }
1702
1703 client->state = NS_CLIENTSTATE_READY;
1704
1705 isc_task_pause(client->task);
1706 if (client->handle == NULL) {
1707 isc_nmhandle_setdata(handle, client, ns__client_reset_cb,
1708 ns__client_put_cb);
1709 client->handle = handle;
1710 }
1711
1712 if (isc_nmhandle_is_stream(handle)) {
1713 client->attributes |= NS_CLIENTATTR_TCP;
1714 }
1715
1716 INSIST(client->recursionquota == NULL);
1717
1718 INSIST(client->state == NS_CLIENTSTATE_READY);
1719
1720 (void)atomic_fetch_add_relaxed(&ns_client_requests, 1);
1721
1722 isc_buffer_init(&tbuffer, region->base, region->length);
1723 isc_buffer_add(&tbuffer, region->length);
1724 buffer = &tbuffer;
1725
1726 client->peeraddr = isc_nmhandle_peeraddr(handle);
1727 client->peeraddr_valid = true;
1728
1729 reqsize = isc_buffer_usedlength(buffer);
1730
1731 client->state = NS_CLIENTSTATE_WORKING;
1732
1733 TIME_NOW(&client->requesttime);
1734 client->tnow = client->requesttime;
1735 client->now = isc_time_seconds(&client->tnow);
1736
1737 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1738
1739 #if NS_CLIENT_DROPPORT
1740 if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1741 DROPPORT_REQUEST)
1742 {
1743 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1744 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1745 "dropped request: suspicious port");
1746 isc_task_unpause(client->task);
1747 return;
1748 }
1749 #endif /* if NS_CLIENT_DROPPORT */
1750
1751 env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
1752 if (client->sctx->blackholeacl != NULL &&
1753 (dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl, env,
1754 &match, NULL) == ISC_R_SUCCESS) &&
1755 match > 0)
1756 {
1757 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1758 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1759 "dropped request: blackholed peer");
1760 isc_task_unpause(client->task);
1761 return;
1762 }
1763
1764 ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
1765 ISC_LOG_DEBUG(3), "%s request",
1766 TCP_CLIENT(client) ? "TCP" : "UDP");
1767
1768 result = dns_message_peekheader(buffer, &id, &flags);
1769 if (result != ISC_R_SUCCESS) {
1770 /*
1771 * There isn't enough header to determine whether
1772 * this was a request or a response. Drop it.
1773 */
1774 isc_task_unpause(client->task);
1775 return;
1776 }
1777
1778 /*
1779 * The client object handles requests, not responses.
1780 * If this is a UDP response, forward it to the dispatcher.
1781 * If it's a TCP response, discard it here.
1782 */
1783 if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1784 CTRACE("unexpected response");
1785 isc_task_unpause(client->task);
1786 return;
1787 }
1788
1789 /*
1790 * Update some statistics counters. Don't count responses.
1791 */
1792 if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1793 ns_stats_increment(client->sctx->nsstats,
1794 ns_statscounter_requestv4);
1795 } else {
1796 ns_stats_increment(client->sctx->nsstats,
1797 ns_statscounter_requestv6);
1798 }
1799 if (TCP_CLIENT(client)) {
1800 ns_stats_increment(client->sctx->nsstats,
1801 ns_statscounter_requesttcp);
1802 switch (isc_sockaddr_pf(&client->peeraddr)) {
1803 case AF_INET:
1804 isc_stats_increment(client->sctx->tcpinstats4,
1805 ISC_MIN((int)reqsize / 16, 18));
1806 break;
1807 case AF_INET6:
1808 isc_stats_increment(client->sctx->tcpinstats6,
1809 ISC_MIN((int)reqsize / 16, 18));
1810 break;
1811 default:
1812 INSIST(0);
1813 ISC_UNREACHABLE();
1814 }
1815 } else {
1816 switch (isc_sockaddr_pf(&client->peeraddr)) {
1817 case AF_INET:
1818 isc_stats_increment(client->sctx->udpinstats4,
1819 ISC_MIN((int)reqsize / 16, 18));
1820 break;
1821 case AF_INET6:
1822 isc_stats_increment(client->sctx->udpinstats6,
1823 ISC_MIN((int)reqsize / 16, 18));
1824 break;
1825 default:
1826 INSIST(0);
1827 ISC_UNREACHABLE();
1828 }
1829 }
1830
1831 /*
1832 * It's a request. Parse it.
1833 */
1834 result = dns_message_parse(client->message, buffer, 0);
1835 if (result != ISC_R_SUCCESS) {
1836 /*
1837 * Parsing the request failed. Send a response
1838 * (typically FORMERR or SERVFAIL).
1839 */
1840 if (result == DNS_R_OPTERR) {
1841 (void)ns_client_addopt(client, client->message,
1842 &client->opt);
1843 }
1844
1845 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1846 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1847 "message parsing failed: %s",
1848 isc_result_totext(result));
1849 if (result == ISC_R_NOSPACE || result == DNS_R_BADTSIG) {
1850 result = DNS_R_FORMERR;
1851 }
1852 ns_client_error(client, result);
1853 isc_task_unpause(client->task);
1854 return;
1855 }
1856
1857 /*
1858 * Disable pipelined TCP query processing if necessary.
1859 */
1860 if (TCP_CLIENT(client) &&
1861 (client->message->opcode != dns_opcode_query ||
1862 (client->sctx->keepresporder != NULL &&
1863 dns_acl_allowed(&netaddr, NULL, client->sctx->keepresporder,
1864 env))))
1865 {
1866 isc_nm_tcpdns_sequential(handle);
1867 }
1868
1869 dns_opcodestats_increment(client->sctx->opcodestats,
1870 client->message->opcode);
1871 switch (client->message->opcode) {
1872 case dns_opcode_query:
1873 case dns_opcode_update:
1874 case dns_opcode_notify:
1875 notimp = false;
1876 break;
1877 case dns_opcode_iquery:
1878 default:
1879 notimp = true;
1880 break;
1881 }
1882
1883 client->message->rcode = dns_rcode_noerror;
1884
1885 /*
1886 * Deal with EDNS.
1887 */
1888 if ((client->sctx->options & NS_SERVER_NOEDNS) != 0) {
1889 opt = NULL;
1890 } else {
1891 opt = dns_message_getopt(client->message);
1892 }
1893
1894 client->ecs.source = 0;
1895 client->ecs.scope = 0;
1896
1897 if (opt != NULL) {
1898 /*
1899 * Are returning FORMERR to all EDNS queries?
1900 * Simulate a STD13 compliant server.
1901 */
1902 if ((client->sctx->options & NS_SERVER_EDNSFORMERR) != 0) {
1903 ns_client_error(client, DNS_R_FORMERR);
1904 isc_task_unpause(client->task);
1905 return;
1906 }
1907
1908 /*
1909 * Are returning NOTIMP to all EDNS queries?
1910 */
1911 if ((client->sctx->options & NS_SERVER_EDNSNOTIMP) != 0) {
1912 ns_client_error(client, DNS_R_NOTIMP);
1913 isc_task_unpause(client->task);
1914 return;
1915 }
1916
1917 /*
1918 * Are returning REFUSED to all EDNS queries?
1919 */
1920 if ((client->sctx->options & NS_SERVER_EDNSREFUSED) != 0) {
1921 ns_client_error(client, DNS_R_REFUSED);
1922 isc_task_unpause(client->task);
1923 return;
1924 }
1925
1926 /*
1927 * Are we dropping all EDNS queries?
1928 */
1929 if ((client->sctx->options & NS_SERVER_DROPEDNS) != 0) {
1930 ns_client_drop(client, ISC_R_SUCCESS);
1931 isc_task_unpause(client->task);
1932 return;
1933 }
1934
1935 result = process_opt(client, opt);
1936 if (result != ISC_R_SUCCESS) {
1937 isc_task_unpause(client->task);
1938 return;
1939 }
1940 }
1941
1942 if (client->message->rdclass == 0) {
1943 if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 &&
1944 client->message->opcode == dns_opcode_query &&
1945 client->message->counts[DNS_SECTION_QUESTION] == 0U)
1946 {
1947 result = dns_message_reply(client->message, true);
1948 if (result != ISC_R_SUCCESS) {
1949 ns_client_error(client, result);
1950 isc_task_unpause(client->task);
1951 return;
1952 }
1953
1954 if (notimp) {
1955 client->message->rcode = dns_rcode_notimp;
1956 }
1957
1958 ns_client_send(client);
1959 isc_task_unpause(client->task);
1960 return;
1961 }
1962
1963 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1964 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1965 "message class could not be determined");
1966 ns_client_dumpmessage(client, "message class could not be "
1967 "determined");
1968 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1969 isc_task_unpause(client->task);
1970 return;
1971 }
1972
1973 /*
1974 * Determine the destination address. If the receiving interface is
1975 * bound to a specific address, we simply use it regardless of the
1976 * address family. All IPv4 queries should fall into this case.
1977 * Otherwise, if this is a TCP query, get the address from the
1978 * receiving socket (this needs a system call and can be heavy).
1979 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1980 * supported).
1981 *
1982 * If all the attempts fail (this can happen due to memory shortage,
1983 * etc), we regard this as an error for safety.
1984 */
1985 if ((client->manager->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1986 {
1987 isc_netaddr_fromsockaddr(&client->destaddr,
1988 &client->manager->interface->addr);
1989 } else {
1990 isc_sockaddr_t sockaddr = isc_nmhandle_localaddr(handle);
1991 isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
1992 }
1993
1994 isc_sockaddr_fromnetaddr(&client->destsockaddr, &client->destaddr, 0);
1995
1996 result = client->sctx->matchingview(&netaddr, &client->destaddr,
1997 client->message, env, &sigresult,
1998 &client->view);
1999 if (result != ISC_R_SUCCESS) {
2000 char classname[DNS_RDATACLASS_FORMATSIZE];
2001
2002 /*
2003 * Do a dummy TSIG verification attempt so that the
2004 * response will have a TSIG if the query did, as
2005 * required by RFC2845.
2006 */
2007 isc_buffer_t b;
2008 isc_region_t *r;
2009
2010 dns_message_resetsig(client->message);
2011
2012 r = dns_message_getrawmessage(client->message);
2013 isc_buffer_init(&b, r->base, r->length);
2014 isc_buffer_add(&b, r->length);
2015 (void)dns_tsig_verify(&b, client->message, NULL, NULL);
2016
2017 dns_rdataclass_format(client->message->rdclass, classname,
2018 sizeof(classname));
2019 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2020 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2021 "no matching view in class '%s'", classname);
2022 ns_client_dumpmessage(client, "no matching view in class");
2023 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
2024 isc_task_unpause(client->task);
2025 return;
2026 }
2027
2028 ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
2029 ISC_LOG_DEBUG(5), "using view '%s'", client->view->name);
2030
2031 /*
2032 * Check for a signature. We log bad signatures regardless of
2033 * whether they ultimately cause the request to be rejected or
2034 * not. We do not log the lack of a signature unless we are
2035 * debugging.
2036 */
2037 client->signer = NULL;
2038 dns_name_init(&client->signername, NULL);
2039 result = dns_message_signer(client->message, &client->signername);
2040 if (result != ISC_R_NOTFOUND) {
2041 signame = NULL;
2042 if (dns_message_gettsig(client->message, &signame) != NULL) {
2043 ns_stats_increment(client->sctx->nsstats,
2044 ns_statscounter_tsigin);
2045 } else {
2046 ns_stats_increment(client->sctx->nsstats,
2047 ns_statscounter_sig0in);
2048 }
2049 }
2050 if (result == ISC_R_SUCCESS) {
2051 char namebuf[DNS_NAME_FORMATSIZE];
2052 dns_name_format(&client->signername, namebuf, sizeof(namebuf));
2053 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2054 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2055 "request has valid signature: %s", namebuf);
2056 client->signer = &client->signername;
2057 } else if (result == ISC_R_NOTFOUND) {
2058 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2059 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2060 "request is not signed");
2061 } else if (result == DNS_R_NOIDENTITY) {
2062 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2063 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2064 "request is signed by a nonauthoritative key");
2065 } else {
2066 char tsigrcode[64];
2067 isc_buffer_t b;
2068 dns_rcode_t status;
2069 isc_result_t tresult;
2070
2071 /* There is a signature, but it is bad. */
2072 ns_stats_increment(client->sctx->nsstats,
2073 ns_statscounter_invalidsig);
2074 signame = NULL;
2075 if (dns_message_gettsig(client->message, &signame) != NULL) {
2076 char namebuf[DNS_NAME_FORMATSIZE];
2077 char cnamebuf[DNS_NAME_FORMATSIZE];
2078 dns_name_format(signame, namebuf, sizeof(namebuf));
2079 status = client->message->tsigstatus;
2080 isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
2081 tresult = dns_tsigrcode_totext(status, &b);
2082 INSIST(tresult == ISC_R_SUCCESS);
2083 tsigrcode[isc_buffer_usedlength(&b)] = '\0';
2084 if (client->message->tsigkey->generated) {
2085 dns_name_format(
2086 client->message->tsigkey->creator,
2087 cnamebuf, sizeof(cnamebuf));
2088 ns_client_log(
2089 client, DNS_LOGCATEGORY_SECURITY,
2090 NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
2091 "request has invalid signature: "
2092 "TSIG %s (%s): %s (%s)",
2093 namebuf, cnamebuf,
2094 isc_result_totext(result), tsigrcode);
2095 } else {
2096 ns_client_log(
2097 client, DNS_LOGCATEGORY_SECURITY,
2098 NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
2099 "request has invalid signature: "
2100 "TSIG %s: %s (%s)",
2101 namebuf, isc_result_totext(result),
2102 tsigrcode);
2103 }
2104 } else {
2105 status = client->message->sig0status;
2106 isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
2107 tresult = dns_tsigrcode_totext(status, &b);
2108 INSIST(tresult == ISC_R_SUCCESS);
2109 tsigrcode[isc_buffer_usedlength(&b)] = '\0';
2110 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2111 NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
2112 "request has invalid signature: %s (%s)",
2113 isc_result_totext(result), tsigrcode);
2114 }
2115
2116 /*
2117 * Accept update messages signed by unknown keys so that
2118 * update forwarding works transparently through slaves
2119 * that don't have all the same keys as the master.
2120 */
2121 if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
2122 client->message->opcode == dns_opcode_update))
2123 {
2124 ns_client_error(client, sigresult);
2125 isc_task_unpause(client->task);
2126 return;
2127 }
2128 }
2129
2130 /*
2131 * Decide whether recursive service is available to this client.
2132 * We do this here rather than in the query code so that we can
2133 * set the RA bit correctly on all kinds of responses, not just
2134 * responses to ordinary queries. Note if you can't query the
2135 * cache there is no point in setting RA.
2136 */
2137 ra = false;
2138 if (client->view->resolver != NULL && client->view->recursion &&
2139 ns_client_checkaclsilent(client, NULL, client->view->recursionacl,
2140 true) == ISC_R_SUCCESS &&
2141 ns_client_checkaclsilent(client, NULL, client->view->cacheacl,
2142 true) == ISC_R_SUCCESS &&
2143 ns_client_checkaclsilent(client, &client->destaddr,
2144 client->view->recursiononacl,
2145 true) == ISC_R_SUCCESS &&
2146 ns_client_checkaclsilent(client, &client->destaddr,
2147 client->view->cacheonacl,
2148 true) == ISC_R_SUCCESS)
2149 {
2150 ra = true;
2151 }
2152
2153 if (ra) {
2154 client->attributes |= NS_CLIENTATTR_RA;
2155 }
2156
2157 ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
2158 ISC_LOG_DEBUG(3),
2159 ra ? "recursion available" : "recursion not available");
2160
2161 /*
2162 * Adjust maximum UDP response size for this client.
2163 */
2164 if (client->udpsize > 512) {
2165 dns_peer_t *peer = NULL;
2166 uint16_t udpsize = client->view->maxudp;
2167 (void)dns_peerlist_peerbyaddr(client->view->peers, &netaddr,
2168 &peer);
2169 if (peer != NULL) {
2170 dns_peer_getmaxudp(peer, &udpsize);
2171 }
2172 if (client->udpsize > udpsize) {
2173 client->udpsize = udpsize;
2174 }
2175 }
2176
2177 /*
2178 * Dispatch the request.
2179 */
2180 switch (client->message->opcode) {
2181 case dns_opcode_query:
2182 CTRACE("query");
2183 #ifdef HAVE_DNSTAP
2184 if (ra && (client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
2185 dtmsgtype = DNS_DTTYPE_CQ;
2186 } else {
2187 dtmsgtype = DNS_DTTYPE_AQ;
2188 }
2189
2190 dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
2191 &client->destsockaddr, TCP_CLIENT(client), NULL,
2192 &client->requesttime, NULL, buffer);
2193 #endif /* HAVE_DNSTAP */
2194
2195 ns_query_start(client, handle);
2196 break;
2197 case dns_opcode_update:
2198 CTRACE("update");
2199 #ifdef HAVE_DNSTAP
2200 dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr,
2201 &client->destsockaddr, TCP_CLIENT(client), NULL,
2202 &client->requesttime, NULL, buffer);
2203 #endif /* HAVE_DNSTAP */
2204 ns_client_settimeout(client, 60);
2205 ns_update_start(client, handle, sigresult);
2206 break;
2207 case dns_opcode_notify:
2208 CTRACE("notify");
2209 ns_client_settimeout(client, 60);
2210 ns_notify_start(client, handle);
2211 break;
2212 case dns_opcode_iquery:
2213 CTRACE("iquery");
2214 ns_client_error(client, DNS_R_NOTIMP);
2215 break;
2216 default:
2217 CTRACE("unknown opcode");
2218 ns_client_error(client, DNS_R_NOTIMP);
2219 }
2220
2221 isc_task_unpause(client->task);
2222 }
2223
2224 isc_result_t
ns__client_tcpconn(isc_nmhandle_t * handle,isc_result_t result,void * arg)2225 ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
2226 ns_interface_t *ifp = (ns_interface_t *)arg;
2227 dns_aclenv_t *env = ns_interfacemgr_getaclenv(ifp->mgr);
2228 ns_server_t *sctx = ns_interfacemgr_getserver(ifp->mgr);
2229 unsigned int tcpquota;
2230 isc_sockaddr_t peeraddr;
2231 isc_netaddr_t netaddr;
2232 int match;
2233
2234 if (result != ISC_R_SUCCESS) {
2235 return (result);
2236 }
2237
2238 if (handle != NULL) {
2239 peeraddr = isc_nmhandle_peeraddr(handle);
2240 isc_netaddr_fromsockaddr(&netaddr, &peeraddr);
2241
2242 if (sctx->blackholeacl != NULL &&
2243 (dns_acl_match(&netaddr, NULL, sctx->blackholeacl, env,
2244 &match, NULL) == ISC_R_SUCCESS) &&
2245 match > 0)
2246 {
2247 return (ISC_R_CONNREFUSED);
2248 }
2249 }
2250
2251 tcpquota = isc_quota_getused(&sctx->tcpquota);
2252 ns_stats_update_if_greater(sctx->nsstats, ns_statscounter_tcphighwater,
2253 tcpquota);
2254
2255 return (ISC_R_SUCCESS);
2256 }
2257
2258 static void
get_clientmctx(ns_clientmgr_t * manager,isc_mem_t ** mctxp)2259 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
2260 isc_mem_t *clientmctx;
2261 MTRACE("clientmctx");
2262
2263 int tid = isc_nm_tid();
2264 if (tid < 0) {
2265 tid = isc_random_uniform(manager->ncpus);
2266 }
2267 int rand = isc_random_uniform(CLIENT_NMCTXS_PERCPU);
2268 int nextmctx = (rand * manager->ncpus) + tid;
2269 clientmctx = manager->mctxpool[nextmctx];
2270
2271 isc_mem_attach(clientmctx, mctxp);
2272 }
2273
2274 static void
get_clienttask(ns_clientmgr_t * manager,isc_task_t ** taskp)2275 get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp) {
2276 MTRACE("clienttask");
2277
2278 int tid = isc_nm_tid();
2279 if (tid < 0) {
2280 tid = isc_random_uniform(manager->ncpus);
2281 }
2282
2283 int rand = isc_random_uniform(CLIENT_NTASKS_PERCPU);
2284 int nexttask = (rand * manager->ncpus) + tid;
2285 isc_task_attach(manager->taskpool[nexttask], taskp);
2286 }
2287
2288 isc_result_t
ns__client_setup(ns_client_t * client,ns_clientmgr_t * mgr,bool new)2289 ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
2290 isc_result_t result;
2291
2292 /*
2293 * Caller must be holding the manager lock.
2294 *
2295 * Note: creating a client does not add the client to the
2296 * manager's client list or set the client's manager pointer.
2297 * The caller is responsible for that.
2298 */
2299
2300 REQUIRE(NS_CLIENT_VALID(client) || (new &&client != NULL));
2301 REQUIRE(VALID_MANAGER(mgr) || !new);
2302
2303 if (new) {
2304 *client = (ns_client_t){ .magic = 0 };
2305
2306 get_clientmctx(mgr, &client->mctx);
2307 clientmgr_attach(mgr, &client->manager);
2308 ns_server_attach(mgr->sctx, &client->sctx);
2309 get_clienttask(mgr, &client->task);
2310
2311 dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2312 &client->message);
2313
2314 client->sendbuf = isc_mem_get(client->mctx,
2315 NS_CLIENT_SEND_BUFFER_SIZE);
2316 /*
2317 * Set magic earlier than usual because ns_query_init()
2318 * and the functions it calls will require it.
2319 */
2320 client->magic = NS_CLIENT_MAGIC;
2321 result = ns_query_init(client);
2322 if (result != ISC_R_SUCCESS) {
2323 goto cleanup;
2324 }
2325 } else {
2326 ns_clientmgr_t *oldmgr = client->manager;
2327 ns_server_t *sctx = client->sctx;
2328 isc_task_t *task = client->task;
2329 unsigned char *sendbuf = client->sendbuf;
2330 dns_message_t *message = client->message;
2331 isc_mem_t *oldmctx = client->mctx;
2332 ns_query_t query = client->query;
2333
2334 /*
2335 * Retain these values from the existing client, but
2336 * zero every thing else.
2337 */
2338 *client = (ns_client_t){ .magic = 0,
2339 .mctx = oldmctx,
2340 .manager = oldmgr,
2341 .sctx = sctx,
2342 .task = task,
2343 .sendbuf = sendbuf,
2344 .message = message,
2345 .query = query };
2346 }
2347
2348 client->query.attributes &= ~NS_QUERYATTR_ANSWERED;
2349 client->state = NS_CLIENTSTATE_INACTIVE;
2350 client->udpsize = 512;
2351 client->ednsversion = -1;
2352 dns_name_init(&client->signername, NULL);
2353 dns_ecs_init(&client->ecs);
2354 isc_sockaddr_any(&client->formerrcache.addr);
2355 client->formerrcache.time = 0;
2356 client->formerrcache.id = 0;
2357 ISC_LINK_INIT(client, rlink);
2358 client->rcode_override = -1; /* not set */
2359
2360 client->magic = NS_CLIENT_MAGIC;
2361
2362 CTRACE("client_setup");
2363
2364 return (ISC_R_SUCCESS);
2365
2366 cleanup:
2367 if (client->sendbuf != NULL) {
2368 isc_mem_put(client->mctx, client->sendbuf,
2369 NS_CLIENT_SEND_BUFFER_SIZE);
2370 }
2371
2372 if (client->message != NULL) {
2373 dns_message_detach(&client->message);
2374 }
2375
2376 if (client->task != NULL) {
2377 isc_task_detach(&client->task);
2378 }
2379
2380 if (client->manager != NULL) {
2381 clientmgr_detach(&client->manager);
2382 }
2383 if (client->mctx != NULL) {
2384 isc_mem_detach(&client->mctx);
2385 }
2386 if (client->sctx != NULL) {
2387 ns_server_detach(&client->sctx);
2388 }
2389
2390 return (result);
2391 }
2392
2393 bool
ns_client_shuttingdown(ns_client_t * client)2394 ns_client_shuttingdown(ns_client_t *client) {
2395 return (client->shuttingdown);
2396 }
2397
2398 /***
2399 *** Client Manager
2400 ***/
2401
2402 static void
clientmgr_attach(ns_clientmgr_t * source,ns_clientmgr_t ** targetp)2403 clientmgr_attach(ns_clientmgr_t *source, ns_clientmgr_t **targetp) {
2404 int32_t oldrefs;
2405
2406 REQUIRE(VALID_MANAGER(source));
2407 REQUIRE(targetp != NULL && *targetp == NULL);
2408
2409 oldrefs = isc_refcount_increment0(&source->references);
2410 isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
2411 ISC_LOG_DEBUG(3), "clientmgr @%p attach: %d", source,
2412 oldrefs + 1);
2413
2414 *targetp = source;
2415 }
2416
2417 static void
clientmgr_detach(ns_clientmgr_t ** mp)2418 clientmgr_detach(ns_clientmgr_t **mp) {
2419 int32_t oldrefs;
2420 ns_clientmgr_t *mgr = *mp;
2421 *mp = NULL;
2422
2423 oldrefs = isc_refcount_decrement(&mgr->references);
2424 isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
2425 ISC_LOG_DEBUG(3), "clientmgr @%p detach: %d", mgr,
2426 oldrefs - 1);
2427 if (oldrefs == 1) {
2428 clientmgr_destroy(mgr);
2429 }
2430 }
2431
2432 static void
clientmgr_destroy(ns_clientmgr_t * manager)2433 clientmgr_destroy(ns_clientmgr_t *manager) {
2434 int i;
2435
2436 MTRACE("clientmgr_destroy");
2437
2438 isc_refcount_destroy(&manager->references);
2439 manager->magic = 0;
2440
2441 for (i = 0; i < manager->ncpus * CLIENT_NMCTXS_PERCPU; i++) {
2442 isc_mem_detach(&manager->mctxpool[i]);
2443 }
2444 isc_mem_put(manager->mctx, manager->mctxpool,
2445 manager->ncpus * CLIENT_NMCTXS_PERCPU *
2446 sizeof(isc_mem_t *));
2447
2448 if (manager->interface != NULL) {
2449 ns_interface_detach(&manager->interface);
2450 }
2451
2452 isc_mutex_destroy(&manager->lock);
2453 isc_mutex_destroy(&manager->reclock);
2454
2455 if (manager->excl != NULL) {
2456 isc_task_detach(&manager->excl);
2457 }
2458
2459 for (i = 0; i < manager->ncpus * CLIENT_NTASKS_PERCPU; i++) {
2460 if (manager->taskpool[i] != NULL) {
2461 isc_task_detach(&manager->taskpool[i]);
2462 }
2463 }
2464 isc_mem_put(manager->mctx, manager->taskpool,
2465 manager->ncpus * CLIENT_NTASKS_PERCPU *
2466 sizeof(isc_task_t *));
2467 ns_server_detach(&manager->sctx);
2468
2469 isc_mem_put(manager->mctx, manager, sizeof(*manager));
2470 }
2471
2472 isc_result_t
ns_clientmgr_create(isc_mem_t * mctx,ns_server_t * sctx,isc_taskmgr_t * taskmgr,isc_timermgr_t * timermgr,ns_interface_t * interface,int ncpus,ns_clientmgr_t ** managerp)2473 ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
2474 isc_timermgr_t *timermgr, ns_interface_t *interface,
2475 int ncpus, ns_clientmgr_t **managerp) {
2476 ns_clientmgr_t *manager;
2477 isc_result_t result;
2478 int i;
2479 int npools;
2480
2481 manager = isc_mem_get(mctx, sizeof(*manager));
2482 *manager = (ns_clientmgr_t){ .magic = 0 };
2483
2484 isc_mutex_init(&manager->lock);
2485 isc_mutex_init(&manager->reclock);
2486
2487 manager->excl = NULL;
2488 result = isc_taskmgr_excltask(taskmgr, &manager->excl);
2489 if (result != ISC_R_SUCCESS) {
2490 goto cleanup_reclock;
2491 }
2492
2493 manager->mctx = mctx;
2494 manager->taskmgr = taskmgr;
2495 manager->timermgr = timermgr;
2496 manager->ncpus = ncpus;
2497
2498 ns_interface_attach(interface, &manager->interface);
2499
2500 manager->exiting = false;
2501 int ntasks = CLIENT_NTASKS_PERCPU * manager->ncpus;
2502 manager->taskpool = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
2503 for (i = 0; i < ntasks; i++) {
2504 manager->taskpool[i] = NULL;
2505 result = isc_task_create_bound(manager->taskmgr, 20,
2506 &manager->taskpool[i],
2507 i % CLIENT_NTASKS_PERCPU);
2508 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2509 }
2510 isc_refcount_init(&manager->references, 1);
2511 manager->sctx = NULL;
2512 ns_server_attach(sctx, &manager->sctx);
2513
2514 ISC_LIST_INIT(manager->recursing);
2515
2516 npools = CLIENT_NMCTXS_PERCPU * manager->ncpus;
2517 manager->mctxpool = isc_mem_get(manager->mctx,
2518 npools * sizeof(isc_mem_t *));
2519 for (i = 0; i < npools; i++) {
2520 manager->mctxpool[i] = NULL;
2521 isc_mem_create(&manager->mctxpool[i]);
2522 isc_mem_setname(manager->mctxpool[i], "client", NULL);
2523 }
2524
2525 manager->magic = MANAGER_MAGIC;
2526
2527 MTRACE("create");
2528
2529 *managerp = manager;
2530
2531 return (ISC_R_SUCCESS);
2532
2533 cleanup_reclock:
2534 isc_mutex_destroy(&manager->reclock);
2535 isc_mutex_destroy(&manager->lock);
2536
2537 isc_mem_put(mctx, manager, sizeof(*manager));
2538
2539 return (result);
2540 }
2541
2542 void
ns_clientmgr_destroy(ns_clientmgr_t ** managerp)2543 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2544 isc_result_t result;
2545 ns_clientmgr_t *manager;
2546 bool unlock = false;
2547
2548 REQUIRE(managerp != NULL);
2549 manager = *managerp;
2550 *managerp = NULL;
2551 REQUIRE(VALID_MANAGER(manager));
2552
2553 MTRACE("destroy");
2554
2555 /*
2556 * Check for success because we may already be task-exclusive
2557 * at this point. Only if we succeed at obtaining an exclusive
2558 * lock now will we need to relinquish it later.
2559 */
2560 result = isc_task_beginexclusive(manager->excl);
2561 if (result == ISC_R_SUCCESS) {
2562 unlock = true;
2563 }
2564
2565 manager->exiting = true;
2566
2567 if (unlock) {
2568 isc_task_endexclusive(manager->excl);
2569 }
2570
2571 if (isc_refcount_decrement(&manager->references) == 1) {
2572 clientmgr_destroy(manager);
2573 }
2574 }
2575
2576 isc_sockaddr_t *
ns_client_getsockaddr(ns_client_t * client)2577 ns_client_getsockaddr(ns_client_t *client) {
2578 return (&client->peeraddr);
2579 }
2580
2581 isc_sockaddr_t *
ns_client_getdestaddr(ns_client_t * client)2582 ns_client_getdestaddr(ns_client_t *client) {
2583 return (&client->destsockaddr);
2584 }
2585
2586 isc_result_t
ns_client_checkaclsilent(ns_client_t * client,isc_netaddr_t * netaddr,dns_acl_t * acl,bool default_allow)2587 ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
2588 dns_acl_t *acl, bool default_allow) {
2589 isc_result_t result;
2590 dns_aclenv_t *env =
2591 ns_interfacemgr_getaclenv(client->manager->interface->mgr);
2592 isc_netaddr_t tmpnetaddr;
2593 int match;
2594
2595 if (acl == NULL) {
2596 if (default_allow) {
2597 goto allow;
2598 } else {
2599 goto deny;
2600 }
2601 }
2602
2603 if (netaddr == NULL) {
2604 isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
2605 netaddr = &tmpnetaddr;
2606 }
2607
2608 result = dns_acl_match(netaddr, client->signer, acl, env, &match, NULL);
2609 if (result != ISC_R_SUCCESS) {
2610 goto deny; /* Internal error, already logged. */
2611 }
2612
2613 if (match > 0) {
2614 goto allow;
2615 }
2616 goto deny; /* Negative match or no match. */
2617
2618 allow:
2619 return (ISC_R_SUCCESS);
2620
2621 deny:
2622 return (DNS_R_REFUSED);
2623 }
2624
2625 isc_result_t
ns_client_checkacl(ns_client_t * client,isc_sockaddr_t * sockaddr,const char * opname,dns_acl_t * acl,bool default_allow,int log_level)2626 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2627 const char *opname, dns_acl_t *acl, bool default_allow,
2628 int log_level) {
2629 isc_result_t result;
2630 isc_netaddr_t netaddr;
2631
2632 if (sockaddr != NULL) {
2633 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2634 }
2635
2636 result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
2637 acl, default_allow);
2638
2639 if (result == ISC_R_SUCCESS) {
2640 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2641 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2642 "%s approved", opname);
2643 } else {
2644 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2645 NS_LOGMODULE_CLIENT, log_level, "%s denied",
2646 opname);
2647 }
2648 return (result);
2649 }
2650
2651 static void
ns_client_name(ns_client_t * client,char * peerbuf,size_t len)2652 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2653 if (client->peeraddr_valid) {
2654 isc_sockaddr_format(&client->peeraddr, peerbuf,
2655 (unsigned int)len);
2656 } else {
2657 snprintf(peerbuf, len, "@%p", client);
2658 }
2659 }
2660
2661 void
ns_client_logv(ns_client_t * client,isc_logcategory_t * category,isc_logmodule_t * module,int level,const char * fmt,va_list ap)2662 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2663 isc_logmodule_t *module, int level, const char *fmt,
2664 va_list ap) {
2665 char msgbuf[4096];
2666 char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE];
2667 char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2668 const char *viewname = "";
2669 const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = "";
2670 const char *signer = "", *qname = "";
2671 dns_name_t *q = NULL;
2672
2673 REQUIRE(client != NULL);
2674
2675 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2676
2677 if (client->signer != NULL) {
2678 dns_name_format(client->signer, signerbuf, sizeof(signerbuf));
2679 sep1 = "/key ";
2680 signer = signerbuf;
2681 }
2682
2683 q = client->query.origqname != NULL ? client->query.origqname
2684 : client->query.qname;
2685 if (q != NULL) {
2686 dns_name_format(q, qnamebuf, sizeof(qnamebuf));
2687 sep2 = " (";
2688 sep3 = ")";
2689 qname = qnamebuf;
2690 }
2691
2692 if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2693 strcmp(client->view->name, "_default") != 0)
2694 {
2695 sep4 = ": view ";
2696 viewname = client->view->name;
2697 }
2698
2699 if (client->peeraddr_valid) {
2700 isc_sockaddr_format(&client->peeraddr, peerbuf,
2701 sizeof(peerbuf));
2702 } else {
2703 snprintf(peerbuf, sizeof(peerbuf), "(no-peer)");
2704 }
2705
2706 isc_log_write(ns_lctx, category, module, level,
2707 "client @%p %s%s%s%s%s%s%s%s: %s", client, peerbuf, sep1,
2708 signer, sep2, qname, sep3, sep4, viewname, msgbuf);
2709 }
2710
2711 void
ns_client_log(ns_client_t * client,isc_logcategory_t * category,isc_logmodule_t * module,int level,const char * fmt,...)2712 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2713 isc_logmodule_t *module, int level, const char *fmt, ...) {
2714 va_list ap;
2715
2716 if (!isc_log_wouldlog(ns_lctx, level)) {
2717 return;
2718 }
2719
2720 va_start(ap, fmt);
2721 ns_client_logv(client, category, module, level, fmt, ap);
2722 va_end(ap);
2723 }
2724
2725 void
ns_client_aclmsg(const char * msg,const dns_name_t * name,dns_rdatatype_t type,dns_rdataclass_t rdclass,char * buf,size_t len)2726 ns_client_aclmsg(const char *msg, const dns_name_t *name, dns_rdatatype_t type,
2727 dns_rdataclass_t rdclass, char *buf, size_t len) {
2728 char namebuf[DNS_NAME_FORMATSIZE];
2729 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2730 char classbuf[DNS_RDATACLASS_FORMATSIZE];
2731
2732 dns_name_format(name, namebuf, sizeof(namebuf));
2733 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2734 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2735 (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2736 classbuf);
2737 }
2738
2739 static void
ns_client_dumpmessage(ns_client_t * client,const char * reason)2740 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2741 isc_buffer_t buffer;
2742 char *buf = NULL;
2743 int len = 1024;
2744 isc_result_t result;
2745
2746 if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) {
2747 return;
2748 }
2749
2750 /*
2751 * Note that these are multiline debug messages. We want a newline
2752 * to appear in the log after each message.
2753 */
2754
2755 do {
2756 buf = isc_mem_get(client->mctx, len);
2757 isc_buffer_init(&buffer, buf, len);
2758 result = dns_message_totext(
2759 client->message, &dns_master_style_debug, 0, &buffer);
2760 if (result == ISC_R_NOSPACE) {
2761 isc_mem_put(client->mctx, buf, len);
2762 len += 1024;
2763 } else if (result == ISC_R_SUCCESS) {
2764 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2765 NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2766 "%s\n%.*s", reason,
2767 (int)isc_buffer_usedlength(&buffer), buf);
2768 }
2769 } while (result == ISC_R_NOSPACE);
2770
2771 if (buf != NULL) {
2772 isc_mem_put(client->mctx, buf, len);
2773 }
2774 }
2775
2776 void
ns_client_dumprecursing(FILE * f,ns_clientmgr_t * manager)2777 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2778 ns_client_t *client;
2779 char namebuf[DNS_NAME_FORMATSIZE];
2780 char original[DNS_NAME_FORMATSIZE];
2781 char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2782 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2783 char classbuf[DNS_RDATACLASS_FORMATSIZE];
2784 const char *name;
2785 const char *sep;
2786 const char *origfor;
2787 dns_rdataset_t *rdataset;
2788
2789 REQUIRE(VALID_MANAGER(manager));
2790
2791 LOCK(&manager->reclock);
2792 client = ISC_LIST_HEAD(manager->recursing);
2793 while (client != NULL) {
2794 INSIST(client->state == NS_CLIENTSTATE_RECURSING);
2795
2796 ns_client_name(client, peerbuf, sizeof(peerbuf));
2797 if (client->view != NULL &&
2798 strcmp(client->view->name, "_bind") != 0 &&
2799 strcmp(client->view->name, "_default") != 0)
2800 {
2801 name = client->view->name;
2802 sep = ": view ";
2803 } else {
2804 name = "";
2805 sep = "";
2806 }
2807
2808 LOCK(&client->query.fetchlock);
2809 INSIST(client->query.qname != NULL);
2810 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2811 if (client->query.qname != client->query.origqname &&
2812 client->query.origqname != NULL)
2813 {
2814 origfor = " for ";
2815 dns_name_format(client->query.origqname, original,
2816 sizeof(original));
2817 } else {
2818 origfor = "";
2819 original[0] = '\0';
2820 }
2821 rdataset = ISC_LIST_HEAD(client->query.qname->list);
2822 if (rdataset == NULL && client->query.origqname != NULL) {
2823 rdataset = ISC_LIST_HEAD(client->query.origqname->list);
2824 }
2825 if (rdataset != NULL) {
2826 dns_rdatatype_format(rdataset->type, typebuf,
2827 sizeof(typebuf));
2828 dns_rdataclass_format(rdataset->rdclass, classbuf,
2829 sizeof(classbuf));
2830 } else {
2831 strlcpy(typebuf, "-", sizeof(typebuf));
2832 strlcpy(classbuf, "-", sizeof(classbuf));
2833 }
2834 UNLOCK(&client->query.fetchlock);
2835 fprintf(f,
2836 "; client %s%s%s: id %u '%s/%s/%s'%s%s "
2837 "requesttime %u\n",
2838 peerbuf, sep, name, client->message->id, namebuf,
2839 typebuf, classbuf, origfor, original,
2840 isc_time_seconds(&client->requesttime));
2841 client = ISC_LIST_NEXT(client, rlink);
2842 }
2843 UNLOCK(&manager->reclock);
2844 }
2845
2846 void
ns_client_qnamereplace(ns_client_t * client,dns_name_t * name)2847 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2848 LOCK(&client->query.fetchlock);
2849 if (client->query.restarts > 0) {
2850 /*
2851 * client->query.qname was dynamically allocated.
2852 */
2853 dns_message_puttempname(client->message, &client->query.qname);
2854 }
2855 client->query.qname = name;
2856 client->query.attributes &= ~NS_QUERYATTR_REDIRECT;
2857 UNLOCK(&client->query.fetchlock);
2858 }
2859
2860 isc_result_t
ns_client_sourceip(dns_clientinfo_t * ci,isc_sockaddr_t ** addrp)2861 ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) {
2862 ns_client_t *client = (ns_client_t *)ci->data;
2863
2864 REQUIRE(NS_CLIENT_VALID(client));
2865 REQUIRE(addrp != NULL);
2866
2867 *addrp = &client->peeraddr;
2868 return (ISC_R_SUCCESS);
2869 }
2870
2871 dns_rdataset_t *
ns_client_newrdataset(ns_client_t * client)2872 ns_client_newrdataset(ns_client_t *client) {
2873 dns_rdataset_t *rdataset;
2874 isc_result_t result;
2875
2876 REQUIRE(NS_CLIENT_VALID(client));
2877
2878 rdataset = NULL;
2879 result = dns_message_gettemprdataset(client->message, &rdataset);
2880 if (result != ISC_R_SUCCESS) {
2881 return (NULL);
2882 }
2883
2884 return (rdataset);
2885 }
2886
2887 void
ns_client_putrdataset(ns_client_t * client,dns_rdataset_t ** rdatasetp)2888 ns_client_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
2889 dns_rdataset_t *rdataset;
2890
2891 REQUIRE(NS_CLIENT_VALID(client));
2892 REQUIRE(rdatasetp != NULL);
2893
2894 rdataset = *rdatasetp;
2895
2896 if (rdataset != NULL) {
2897 if (dns_rdataset_isassociated(rdataset)) {
2898 dns_rdataset_disassociate(rdataset);
2899 }
2900 dns_message_puttemprdataset(client->message, rdatasetp);
2901 }
2902 }
2903
2904 isc_result_t
ns_client_newnamebuf(ns_client_t * client)2905 ns_client_newnamebuf(ns_client_t *client) {
2906 isc_buffer_t *dbuf = NULL;
2907
2908 CTRACE("ns_client_newnamebuf");
2909
2910 isc_buffer_allocate(client->mctx, &dbuf, 1024);
2911 ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
2912
2913 CTRACE("ns_client_newnamebuf: done");
2914 return (ISC_R_SUCCESS);
2915 }
2916
2917 dns_name_t *
ns_client_newname(ns_client_t * client,isc_buffer_t * dbuf,isc_buffer_t * nbuf)2918 ns_client_newname(ns_client_t *client, isc_buffer_t *dbuf, isc_buffer_t *nbuf) {
2919 dns_name_t *name = NULL;
2920 isc_region_t r;
2921 isc_result_t result;
2922
2923 REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
2924
2925 CTRACE("ns_client_newname");
2926
2927 result = dns_message_gettempname(client->message, &name);
2928 if (result != ISC_R_SUCCESS) {
2929 CTRACE("ns_client_newname: "
2930 "dns_message_gettempname failed: done");
2931 return (NULL);
2932 }
2933 isc_buffer_availableregion(dbuf, &r);
2934 isc_buffer_init(nbuf, r.base, r.length);
2935 dns_name_setbuffer(name, NULL);
2936 dns_name_setbuffer(name, nbuf);
2937 client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
2938
2939 CTRACE("ns_client_newname: done");
2940 return (name);
2941 }
2942
2943 isc_buffer_t *
ns_client_getnamebuf(ns_client_t * client)2944 ns_client_getnamebuf(ns_client_t *client) {
2945 isc_buffer_t *dbuf;
2946 isc_region_t r;
2947
2948 CTRACE("ns_client_getnamebuf");
2949
2950 /*%
2951 * Return a name buffer with space for a maximal name, allocating
2952 * a new one if necessary.
2953 */
2954 if (ISC_LIST_EMPTY(client->query.namebufs)) {
2955 ns_client_newnamebuf(client);
2956 }
2957
2958 dbuf = ISC_LIST_TAIL(client->query.namebufs);
2959 INSIST(dbuf != NULL);
2960 isc_buffer_availableregion(dbuf, &r);
2961 if (r.length < DNS_NAME_MAXWIRE) {
2962 ns_client_newnamebuf(client);
2963 dbuf = ISC_LIST_TAIL(client->query.namebufs);
2964 isc_buffer_availableregion(dbuf, &r);
2965 INSIST(r.length >= 255);
2966 }
2967 CTRACE("ns_client_getnamebuf: done");
2968 return (dbuf);
2969 }
2970
2971 void
ns_client_keepname(ns_client_t * client,dns_name_t * name,isc_buffer_t * dbuf)2972 ns_client_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
2973 isc_region_t r;
2974
2975 CTRACE("ns_client_keepname");
2976
2977 /*%
2978 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
2979 * adjusted to take account of that. We do the adjustment.
2980 */
2981 REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
2982
2983 dns_name_toregion(name, &r);
2984 isc_buffer_add(dbuf, r.length);
2985 dns_name_setbuffer(name, NULL);
2986 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
2987 }
2988
2989 void
ns_client_releasename(ns_client_t * client,dns_name_t ** namep)2990 ns_client_releasename(ns_client_t *client, dns_name_t **namep) {
2991 /*%
2992 * 'name' is no longer needed. Return it to our pool of temporary
2993 * names. If it is using a name buffer, relinquish its exclusive
2994 * rights on the buffer.
2995 */
2996
2997 CTRACE("ns_client_releasename");
2998 client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
2999 dns_message_puttempname(client->message, namep);
3000 CTRACE("ns_client_releasename: done");
3001 }
3002
3003 isc_result_t
ns_client_newdbversion(ns_client_t * client,unsigned int n)3004 ns_client_newdbversion(ns_client_t *client, unsigned int n) {
3005 unsigned int i;
3006 ns_dbversion_t *dbversion = NULL;
3007
3008 for (i = 0; i < n; i++) {
3009 dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
3010 *dbversion = (ns_dbversion_t){ 0 };
3011 ISC_LIST_INITANDAPPEND(client->query.freeversions, dbversion,
3012 link);
3013 }
3014
3015 return (ISC_R_SUCCESS);
3016 }
3017
3018 static inline ns_dbversion_t *
client_getdbversion(ns_client_t * client)3019 client_getdbversion(ns_client_t *client) {
3020 ns_dbversion_t *dbversion = NULL;
3021
3022 if (ISC_LIST_EMPTY(client->query.freeversions)) {
3023 ns_client_newdbversion(client, 1);
3024 }
3025 dbversion = ISC_LIST_HEAD(client->query.freeversions);
3026 INSIST(dbversion != NULL);
3027 ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
3028
3029 return (dbversion);
3030 }
3031
3032 ns_dbversion_t *
ns_client_findversion(ns_client_t * client,dns_db_t * db)3033 ns_client_findversion(ns_client_t *client, dns_db_t *db) {
3034 ns_dbversion_t *dbversion;
3035
3036 for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
3037 dbversion != NULL; dbversion = ISC_LIST_NEXT(dbversion, link))
3038 {
3039 if (dbversion->db == db) {
3040 break;
3041 }
3042 }
3043
3044 if (dbversion == NULL) {
3045 /*
3046 * This is a new zone for this query. Add it to
3047 * the active list.
3048 */
3049 dbversion = client_getdbversion(client);
3050 if (dbversion == NULL) {
3051 return (NULL);
3052 }
3053 dns_db_attach(db, &dbversion->db);
3054 dns_db_currentversion(db, &dbversion->version);
3055 dbversion->acl_checked = false;
3056 dbversion->queryok = false;
3057 ISC_LIST_APPEND(client->query.activeversions, dbversion, link);
3058 }
3059
3060 return (dbversion);
3061 }
3062