2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: controlconf.c,v 1.28.2.10 2004/03/09 06:09:18 marka Exp $ */
22 #include <isc/base64.h>
23 #include <isc/buffer.h>
24 #include <isc/event.h>
26 #include <isc/fsaccess.h>
29 #include <isc/netaddr.h>
30 #include <isc/print.h>
31 #include <isc/random.h>
32 #include <isc/result.h>
33 #include <isc/stdio.h>
34 #include <isc/stdtime.h>
35 #include <isc/string.h>
36 #include <isc/timer.h>
39 #include <isccfg/cfg.h>
40 #include <isccfg/check.h>
42 #include <isccc/alist.h>
44 #include <isccc/ccmsg.h>
45 #include <isccc/events.h>
46 #include <isccc/result.h>
47 #include <isccc/sexpr.h>
48 #include <isccc/symtab.h>
49 #include <isccc/util.h>
51 #include <dns/keyvalues.h>
52 #include <dns/result.h>
56 #include <named/config.h>
57 #include <named/control.h>
58 #include <named/log.h>
59 #include <named/server.h>
62 * Note: Listeners and connections are not locked. All event handlers are
63 * executed by the server task, and all callers of exported routines must
64 * be running under the server task.
67 typedef struct controlkey controlkey_t
;
68 typedef ISC_LIST(controlkey_t
) controlkeylist_t
;
70 typedef struct controlconnection controlconnection_t
;
71 typedef ISC_LIST(controlconnection_t
) controlconnectionlist_t
;
73 typedef struct controllistener controllistener_t
;
74 typedef ISC_LIST(controllistener_t
) controllistenerlist_t
;
79 ISC_LINK(controlkey_t
) link
;
82 struct controlconnection
{
85 isc_boolean_t ccmsg_valid
;
86 isc_boolean_t sending
;
88 unsigned char buffer
[2048];
89 controllistener_t
* listener
;
91 ISC_LINK(controlconnection_t
) link
;
94 struct controllistener
{
95 ns_controls_t
* controls
;
98 isc_sockaddr_t address
;
101 isc_boolean_t listening
;
102 isc_boolean_t exiting
;
103 controlkeylist_t keys
;
104 controlconnectionlist_t connections
;
105 ISC_LINK(controllistener_t
) link
;
110 controllistenerlist_t listeners
;
111 isc_boolean_t shuttingdown
;
112 isccc_symtab_t
*symtab
;
115 static void control_newconn(isc_task_t
*task
, isc_event_t
*event
);
116 static void control_recvmessage(isc_task_t
*task
, isc_event_t
*event
);
118 #define CLOCKSKEW 300
121 free_controlkey(controlkey_t
*key
, isc_mem_t
*mctx
) {
122 if (key
->keyname
!= NULL
)
123 isc_mem_free(mctx
, key
->keyname
);
124 if (key
->secret
.base
!= NULL
)
125 isc_mem_put(mctx
, key
->secret
.base
, key
->secret
.length
);
126 isc_mem_put(mctx
, key
, sizeof(*key
));
130 free_controlkeylist(controlkeylist_t
*keylist
, isc_mem_t
*mctx
) {
131 while (!ISC_LIST_EMPTY(*keylist
)) {
132 controlkey_t
*key
= ISC_LIST_HEAD(*keylist
);
133 ISC_LIST_UNLINK(*keylist
, key
, link
);
134 free_controlkey(key
, mctx
);
139 free_listener(controllistener_t
*listener
) {
140 INSIST(listener
->exiting
);
141 INSIST(!listener
->listening
);
142 INSIST(ISC_LIST_EMPTY(listener
->connections
));
144 if (listener
->sock
!= NULL
)
145 isc_socket_detach(&listener
->sock
);
147 free_controlkeylist(&listener
->keys
, listener
->mctx
);
149 if (listener
->acl
!= NULL
)
150 dns_acl_detach(&listener
->acl
);
152 isc_mem_put(listener
->mctx
, listener
, sizeof(*listener
));
156 maybe_free_listener(controllistener_t
*listener
) {
157 if (listener
->exiting
&&
158 !listener
->listening
&&
159 ISC_LIST_EMPTY(listener
->connections
))
160 free_listener(listener
);
164 maybe_free_connection(controlconnection_t
*conn
) {
165 controllistener_t
*listener
= conn
->listener
;
167 if (conn
->timer
!= NULL
)
168 isc_timer_detach(&conn
->timer
);
170 if (conn
->ccmsg_valid
) {
171 isccc_ccmsg_cancelread(&conn
->ccmsg
);
176 isc_socket_cancel(conn
->sock
, listener
->task
,
177 ISC_SOCKCANCEL_SEND
);
181 ISC_LIST_UNLINK(listener
->connections
, conn
, link
);
182 isc_mem_put(listener
->mctx
, conn
, sizeof(*conn
));
186 shutdown_listener(controllistener_t
*listener
) {
187 controlconnection_t
*conn
;
188 controlconnection_t
*next
;
190 if (!listener
->exiting
) {
191 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
193 ISC_LIST_UNLINK(listener
->controls
->listeners
, listener
, link
);
195 isc_sockaddr_format(&listener
->address
, socktext
,
197 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
198 NS_LOGMODULE_CONTROL
, ISC_LOG_NOTICE
,
199 "stopping command channel on %s", socktext
);
200 listener
->exiting
= ISC_TRUE
;
203 for (conn
= ISC_LIST_HEAD(listener
->connections
);
207 next
= ISC_LIST_NEXT(conn
, link
);
208 maybe_free_connection(conn
);
211 if (listener
->listening
)
212 isc_socket_cancel(listener
->sock
, listener
->task
,
213 ISC_SOCKCANCEL_ACCEPT
);
215 maybe_free_listener(listener
);
219 address_ok(isc_sockaddr_t
*sockaddr
, dns_acl_t
*acl
) {
220 isc_netaddr_t netaddr
;
224 isc_netaddr_fromsockaddr(&netaddr
, sockaddr
);
226 result
= dns_acl_match(&netaddr
, NULL
, acl
,
227 &ns_g_server
->aclenv
, &match
, NULL
);
229 if (result
!= ISC_R_SUCCESS
|| match
<= 0)
236 control_accept(controllistener_t
*listener
) {
238 result
= isc_socket_accept(listener
->sock
,
240 control_newconn
, listener
);
241 if (result
!= ISC_R_SUCCESS
)
242 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
243 "isc_socket_accept() failed: %s",
244 isc_result_totext(result
));
246 listener
->listening
= ISC_TRUE
;
251 control_listen(controllistener_t
*listener
) {
254 result
= isc_socket_listen(listener
->sock
, 0);
255 if (result
!= ISC_R_SUCCESS
)
256 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
257 "isc_socket_listen() failed: %s",
258 isc_result_totext(result
));
263 control_next(controllistener_t
*listener
) {
264 (void)control_accept(listener
);
268 control_senddone(isc_task_t
*task
, isc_event_t
*event
) {
269 isc_socketevent_t
*sevent
= (isc_socketevent_t
*) event
;
270 controlconnection_t
*conn
= event
->ev_arg
;
271 controllistener_t
*listener
= conn
->listener
;
272 isc_socket_t
*sock
= (isc_socket_t
*)sevent
->ev_sender
;
275 REQUIRE(conn
->sending
);
279 conn
->sending
= ISC_FALSE
;
281 if (sevent
->result
!= ISC_R_SUCCESS
&&
282 sevent
->result
!= ISC_R_CANCELED
)
284 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
285 isc_sockaddr_t peeraddr
;
287 (void)isc_socket_getpeername(sock
, &peeraddr
);
288 isc_sockaddr_format(&peeraddr
, socktext
, sizeof(socktext
));
289 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
290 NS_LOGMODULE_CONTROL
, ISC_LOG_WARNING
,
291 "error sending command response to %s: %s",
292 socktext
, isc_result_totext(sevent
->result
));
294 isc_event_free(&event
);
296 result
= isccc_ccmsg_readmessage(&conn
->ccmsg
, listener
->task
,
297 control_recvmessage
, conn
);
298 if (result
!= ISC_R_SUCCESS
) {
299 isc_socket_detach(&conn
->sock
);
300 maybe_free_connection(conn
);
301 maybe_free_listener(listener
);
306 log_invalid(isccc_ccmsg_t
*ccmsg
, isc_result_t result
) {
307 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
308 isc_sockaddr_t peeraddr
;
310 (void)isc_socket_getpeername(ccmsg
->sock
, &peeraddr
);
311 isc_sockaddr_format(&peeraddr
, socktext
, sizeof(socktext
));
312 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
313 NS_LOGMODULE_CONTROL
, ISC_LOG_ERROR
,
314 "invalid command from %s: %s",
315 socktext
, isc_result_totext(result
));
319 control_recvmessage(isc_task_t
*task
, isc_event_t
*event
) {
320 controlconnection_t
*conn
;
321 controllistener_t
*listener
;
323 isccc_sexpr_t
*request
= NULL
;
324 isccc_sexpr_t
*response
= NULL
;
325 isccc_region_t ccregion
;
326 isccc_region_t secret
;
332 char textarray
[1024];
334 isc_result_t eresult
;
335 isccc_sexpr_t
*_ctrl
;
340 REQUIRE(event
->ev_type
== ISCCC_EVENT_CCMSG
);
342 conn
= event
->ev_arg
;
343 listener
= conn
->listener
;
344 secret
.rstart
= NULL
;
346 /* Is the server shutting down? */
347 if (listener
->controls
->shuttingdown
)
350 if (conn
->ccmsg
.result
!= ISC_R_SUCCESS
) {
351 if (conn
->ccmsg
.result
!= ISC_R_CANCELED
&&
352 conn
->ccmsg
.result
!= ISC_R_EOF
)
353 log_invalid(&conn
->ccmsg
, conn
->ccmsg
.result
);
359 for (key
= ISC_LIST_HEAD(listener
->keys
);
361 key
= ISC_LIST_NEXT(key
, link
))
363 ccregion
.rstart
= isc_buffer_base(&conn
->ccmsg
.buffer
);
364 ccregion
.rend
= isc_buffer_used(&conn
->ccmsg
.buffer
);
365 secret
.rstart
= isc_mem_get(listener
->mctx
, key
->secret
.length
);
366 if (secret
.rstart
== NULL
)
368 memcpy(secret
.rstart
, key
->secret
.base
, key
->secret
.length
);
369 secret
.rend
= secret
.rstart
+ key
->secret
.length
;
370 result
= isccc_cc_fromwire(&ccregion
, &request
, &secret
);
371 if (result
== ISC_R_SUCCESS
)
373 else if (result
== ISCCC_R_BADAUTH
) {
375 * For some reason, request is non-NULL when
376 * isccc_cc_fromwire returns ISCCC_R_BADAUTH.
379 isccc_sexpr_free(&request
);
380 isc_mem_put(listener
->mctx
, secret
.rstart
,
381 REGION_SIZE(secret
));
383 log_invalid(&conn
->ccmsg
, result
);
389 log_invalid(&conn
->ccmsg
, ISCCC_R_BADAUTH
);
393 /* We shouldn't be getting a reply. */
394 if (isccc_cc_isreply(request
)) {
395 log_invalid(&conn
->ccmsg
, ISC_R_FAILURE
);
399 isc_stdtime_get(&now
);
402 * Limit exposure to replay attacks.
404 _ctrl
= isccc_alist_lookup(request
, "_ctrl");
406 log_invalid(&conn
->ccmsg
, ISC_R_FAILURE
);
410 if (isccc_cc_lookupuint32(_ctrl
, "_tim", &sent
) == ISC_R_SUCCESS
) {
411 if ((sent
+ CLOCKSKEW
) < now
|| (sent
- CLOCKSKEW
) > now
) {
412 log_invalid(&conn
->ccmsg
, ISCCC_R_CLOCKSKEW
);
416 log_invalid(&conn
->ccmsg
, ISC_R_FAILURE
);
421 * Expire messages that are too old.
423 if (isccc_cc_lookupuint32(_ctrl
, "_exp", &exp
) == ISC_R_SUCCESS
&&
425 log_invalid(&conn
->ccmsg
, ISCCC_R_EXPIRED
);
430 * Duplicate suppression (required for UDP).
432 isccc_cc_cleansymtab(listener
->controls
->symtab
, now
);
433 result
= isccc_cc_checkdup(listener
->controls
->symtab
, request
, now
);
434 if (result
!= ISC_R_SUCCESS
) {
435 if (result
== ISC_R_EXISTS
)
436 result
= ISCCC_R_DUPLICATE
;
437 log_invalid(&conn
->ccmsg
, result
);
441 if (conn
->nonce
!= 0 &&
442 (isccc_cc_lookupuint32(_ctrl
, "_nonce", &nonce
) != ISC_R_SUCCESS
||
443 conn
->nonce
!= nonce
)) {
444 log_invalid(&conn
->ccmsg
, ISCCC_R_BADAUTH
);
451 while (conn
->nonce
== 0)
452 isc_random_get(&conn
->nonce
);
454 isc_buffer_init(&text
, textarray
, sizeof(textarray
));
455 eresult
= ns_control_docommand(request
, &text
);
457 result
= isccc_cc_createresponse(request
, now
, now
+ 60, &response
);
458 if (result
!= ISC_R_SUCCESS
)
460 if (eresult
!= ISC_R_SUCCESS
) {
463 data
= isccc_alist_lookup(response
, "_data");
465 const char *estr
= isc_result_totext(eresult
);
466 if (isccc_cc_definestring(data
, "err", estr
) == NULL
)
471 if (isc_buffer_usedlength(&text
) > 0) {
474 data
= isccc_alist_lookup(response
, "_data");
476 char *str
= (char *)isc_buffer_base(&text
);
477 if (isccc_cc_definestring(data
, "text", str
) == NULL
)
482 _ctrl
= isccc_alist_lookup(response
, "_ctrl");
484 isccc_cc_defineuint32(_ctrl
, "_nonce", conn
->nonce
) == NULL
)
487 ccregion
.rstart
= conn
->buffer
+ 4;
488 ccregion
.rend
= conn
->buffer
+ sizeof(conn
->buffer
);
489 result
= isccc_cc_towire(response
, &ccregion
, &secret
);
490 if (result
!= ISC_R_SUCCESS
)
492 isc_buffer_init(&b
, conn
->buffer
, 4);
493 len
= sizeof(conn
->buffer
) - REGION_SIZE(ccregion
);
494 isc_buffer_putuint32(&b
, len
- 4);
495 r
.base
= conn
->buffer
;
498 result
= isc_socket_send(conn
->sock
, &r
, task
, control_senddone
, conn
);
499 if (result
!= ISC_R_SUCCESS
)
501 conn
->sending
= ISC_TRUE
;
503 if (secret
.rstart
!= NULL
)
504 isc_mem_put(listener
->mctx
, secret
.rstart
,
505 REGION_SIZE(secret
));
507 isccc_sexpr_free(&request
);
508 if (response
!= NULL
)
509 isccc_sexpr_free(&response
);
513 if (secret
.rstart
!= NULL
)
514 isc_mem_put(listener
->mctx
, secret
.rstart
,
515 REGION_SIZE(secret
));
516 isc_socket_detach(&conn
->sock
);
517 isccc_ccmsg_invalidate(&conn
->ccmsg
);
518 conn
->ccmsg_valid
= ISC_FALSE
;
519 maybe_free_connection(conn
);
520 maybe_free_listener(listener
);
522 isccc_sexpr_free(&request
);
523 if (response
!= NULL
)
524 isccc_sexpr_free(&response
);
528 control_timeout(isc_task_t
*task
, isc_event_t
*event
) {
529 controlconnection_t
*conn
= event
->ev_arg
;
533 isc_timer_detach(&conn
->timer
);
534 maybe_free_connection(conn
);
536 isc_event_free(&event
);
540 newconnection(controllistener_t
*listener
, isc_socket_t
*sock
) {
541 controlconnection_t
*conn
;
542 isc_interval_t interval
;
545 conn
= isc_mem_get(listener
->mctx
, sizeof(*conn
));
547 return (ISC_R_NOMEMORY
);
550 isccc_ccmsg_init(listener
->mctx
, sock
, &conn
->ccmsg
);
551 conn
->ccmsg_valid
= ISC_TRUE
;
552 conn
->sending
= ISC_FALSE
;
554 isc_interval_set(&interval
, 60, 0);
555 result
= isc_timer_create(ns_g_timermgr
, isc_timertype_once
,
556 NULL
, &interval
, listener
->task
,
557 control_timeout
, conn
, &conn
->timer
);
558 if (result
!= ISC_R_SUCCESS
)
561 conn
->listener
= listener
;
563 ISC_LINK_INIT(conn
, link
);
565 result
= isccc_ccmsg_readmessage(&conn
->ccmsg
, listener
->task
,
566 control_recvmessage
, conn
);
567 if (result
!= ISC_R_SUCCESS
)
569 isccc_ccmsg_setmaxsize(&conn
->ccmsg
, 2048);
571 ISC_LIST_APPEND(listener
->connections
, conn
, link
);
572 return (ISC_R_SUCCESS
);
575 isccc_ccmsg_invalidate(&conn
->ccmsg
);
576 if (conn
->timer
!= NULL
)
577 isc_timer_detach(&conn
->timer
);
578 isc_mem_put(listener
->mctx
, conn
, sizeof(*conn
));
583 control_newconn(isc_task_t
*task
, isc_event_t
*event
) {
584 isc_socket_newconnev_t
*nevent
= (isc_socket_newconnev_t
*)event
;
585 controllistener_t
*listener
= event
->ev_arg
;
587 isc_sockaddr_t peeraddr
;
592 listener
->listening
= ISC_FALSE
;
594 if (nevent
->result
!= ISC_R_SUCCESS
) {
595 if (nevent
->result
== ISC_R_CANCELED
) {
596 shutdown_listener(listener
);
602 sock
= nevent
->newsocket
;
603 (void)isc_socket_getpeername(sock
, &peeraddr
);
604 if (!address_ok(&peeraddr
, listener
->acl
)) {
605 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
606 isc_sockaddr_format(&peeraddr
, socktext
, sizeof(socktext
));
607 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
608 NS_LOGMODULE_CONTROL
, ISC_LOG_WARNING
,
609 "rejected command channel message from %s",
611 isc_socket_detach(&sock
);
615 result
= newconnection(listener
, sock
);
616 if (result
!= ISC_R_SUCCESS
) {
617 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
618 isc_sockaddr_format(&peeraddr
, socktext
, sizeof(socktext
));
619 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
620 NS_LOGMODULE_CONTROL
, ISC_LOG_WARNING
,
621 "dropped command channel from %s: %s",
622 socktext
, isc_result_totext(result
));
623 isc_socket_detach(&sock
);
628 control_next(listener
);
630 isc_event_free(&event
);
634 controls_shutdown(ns_controls_t
*controls
) {
635 controllistener_t
*listener
;
636 controllistener_t
*next
;
638 for (listener
= ISC_LIST_HEAD(controls
->listeners
);
643 * This is asynchronous. As listeners shut down, they will
644 * call their callbacks.
646 next
= ISC_LIST_NEXT(listener
, link
);
647 shutdown_listener(listener
);
652 ns_controls_shutdown(ns_controls_t
*controls
) {
653 controls_shutdown(controls
);
654 controls
->shuttingdown
= ISC_TRUE
;
658 cfgkeylist_find(cfg_obj_t
*keylist
, const char *keyname
, cfg_obj_t
**objp
) {
659 cfg_listelt_t
*element
;
663 for (element
= cfg_list_first(keylist
);
665 element
= cfg_list_next(element
))
667 obj
= cfg_listelt_value(element
);
668 str
= cfg_obj_asstring(cfg_map_getname(obj
));
669 if (strcasecmp(str
, keyname
) == 0)
673 return (ISC_R_NOTFOUND
);
674 obj
= cfg_listelt_value(element
);
676 return (ISC_R_SUCCESS
);
680 controlkeylist_fromcfg(cfg_obj_t
*keylist
, isc_mem_t
*mctx
,
681 controlkeylist_t
*keyids
)
683 cfg_listelt_t
*element
;
687 controlkey_t
*key
= NULL
;
689 for (element
= cfg_list_first(keylist
);
691 element
= cfg_list_next(element
))
693 obj
= cfg_listelt_value(element
);
694 str
= cfg_obj_asstring(obj
);
695 newstr
= isc_mem_strdup(mctx
, str
);
698 key
= isc_mem_get(mctx
, sizeof(*key
));
701 key
->keyname
= newstr
;
702 key
->secret
.base
= NULL
;
703 key
->secret
.length
= 0;
704 ISC_LINK_INIT(key
, link
);
705 ISC_LIST_APPEND(*keyids
, key
, link
);
709 return (ISC_R_SUCCESS
);
713 isc_mem_free(mctx
, newstr
);
715 isc_mem_put(mctx
, key
, sizeof(*key
));
716 free_controlkeylist(keyids
, mctx
);
717 return (ISC_R_NOMEMORY
);
721 register_keys(cfg_obj_t
*control
, cfg_obj_t
*keylist
,
722 controlkeylist_t
*keyids
, isc_mem_t
*mctx
, const char *socktext
)
724 controlkey_t
*keyid
, *next
;
731 * Find the keys corresponding to the keyids used by this listener.
733 for (keyid
= ISC_LIST_HEAD(*keyids
); keyid
!= NULL
; keyid
= next
) {
734 next
= ISC_LIST_NEXT(keyid
, link
);
736 result
= cfgkeylist_find(keylist
, keyid
->keyname
, &keydef
);
737 if (result
!= ISC_R_SUCCESS
) {
738 cfg_obj_log(control
, ns_g_lctx
, ISC_LOG_WARNING
,
739 "couldn't find key '%s' for use with "
740 "command channel %s",
741 keyid
->keyname
, socktext
);
742 ISC_LIST_UNLINK(*keyids
, keyid
, link
);
743 free_controlkey(keyid
, mctx
);
745 cfg_obj_t
*algobj
= NULL
;
746 cfg_obj_t
*secretobj
= NULL
;
748 char *secretstr
= NULL
;
750 (void)cfg_map_get(keydef
, "algorithm", &algobj
);
751 (void)cfg_map_get(keydef
, "secret", &secretobj
);
752 INSIST(algobj
!= NULL
&& secretobj
!= NULL
);
754 algstr
= cfg_obj_asstring(algobj
);
755 secretstr
= cfg_obj_asstring(secretobj
);
757 if (ns_config_getkeyalgorithm(algstr
, NULL
) !=
760 cfg_obj_log(control
, ns_g_lctx
,
762 "unsupported algorithm '%s' in "
763 "key '%s' for use with command "
765 algstr
, keyid
->keyname
, socktext
);
766 ISC_LIST_UNLINK(*keyids
, keyid
, link
);
767 free_controlkey(keyid
, mctx
);
771 isc_buffer_init(&b
, secret
, sizeof(secret
));
772 result
= isc_base64_decodestring(secretstr
, &b
);
774 if (result
!= ISC_R_SUCCESS
) {
775 cfg_obj_log(keydef
, ns_g_lctx
, ISC_LOG_WARNING
,
776 "secret for key '%s' on "
777 "command channel %s: %s",
778 keyid
->keyname
, socktext
,
779 isc_result_totext(result
));
780 ISC_LIST_UNLINK(*keyids
, keyid
, link
);
781 free_controlkey(keyid
, mctx
);
785 keyid
->secret
.length
= isc_buffer_usedlength(&b
);
786 keyid
->secret
.base
= isc_mem_get(mctx
,
787 keyid
->secret
.length
);
788 if (keyid
->secret
.base
== NULL
) {
789 cfg_obj_log(keydef
, ns_g_lctx
, ISC_LOG_WARNING
,
790 "couldn't register key '%s': "
791 "out of memory", keyid
->keyname
);
792 ISC_LIST_UNLINK(*keyids
, keyid
, link
);
793 free_controlkey(keyid
, mctx
);
796 memcpy(keyid
->secret
.base
, isc_buffer_base(&b
),
797 keyid
->secret
.length
);
805 if (result != ISC_R_SUCCESS) \
810 get_rndckey(isc_mem_t
*mctx
, controlkeylist_t
*keyids
) {
812 cfg_parser_t
*pctx
= NULL
;
813 cfg_obj_t
*config
= NULL
;
814 cfg_obj_t
*key
= NULL
;
815 cfg_obj_t
*algobj
= NULL
;
816 cfg_obj_t
*secretobj
= NULL
;
818 char *secretstr
= NULL
;
819 controlkey_t
*keyid
= NULL
;
823 CHECK(cfg_parser_create(mctx
, ns_g_lctx
, &pctx
));
824 CHECK(cfg_parse_file(pctx
, ns_g_keyfile
, &cfg_type_rndckey
, &config
));
825 CHECK(cfg_map_get(config
, "key", &key
));
827 keyid
= isc_mem_get(mctx
, sizeof(*keyid
));
829 CHECK(ISC_R_NOMEMORY
);
830 keyid
->keyname
= isc_mem_strdup(mctx
,
831 cfg_obj_asstring(cfg_map_getname(key
)));
832 keyid
->secret
.base
= NULL
;
833 keyid
->secret
.length
= 0;
834 ISC_LINK_INIT(keyid
, link
);
835 if (keyid
->keyname
== NULL
)
836 CHECK(ISC_R_NOMEMORY
);
838 CHECK(cfg_check_key(key
, ns_g_lctx
));
840 (void)cfg_map_get(key
, "algorithm", &algobj
);
841 (void)cfg_map_get(key
, "secret", &secretobj
);
842 INSIST(algobj
!= NULL
&& secretobj
!= NULL
);
844 algstr
= cfg_obj_asstring(algobj
);
845 secretstr
= cfg_obj_asstring(secretobj
);
847 if (ns_config_getkeyalgorithm(algstr
, NULL
) != ISC_R_SUCCESS
) {
848 cfg_obj_log(key
, ns_g_lctx
,
850 "unsupported algorithm '%s' in "
851 "key '%s' for use with command "
853 algstr
, keyid
->keyname
);
857 isc_buffer_init(&b
, secret
, sizeof(secret
));
858 result
= isc_base64_decodestring(secretstr
, &b
);
860 if (result
!= ISC_R_SUCCESS
) {
861 cfg_obj_log(key
, ns_g_lctx
, ISC_LOG_WARNING
,
862 "secret for key '%s' on command channel: %s",
863 keyid
->keyname
, isc_result_totext(result
));
867 keyid
->secret
.length
= isc_buffer_usedlength(&b
);
868 keyid
->secret
.base
= isc_mem_get(mctx
,
869 keyid
->secret
.length
);
870 if (keyid
->secret
.base
== NULL
) {
871 cfg_obj_log(key
, ns_g_lctx
, ISC_LOG_WARNING
,
872 "couldn't register key '%s': "
873 "out of memory", keyid
->keyname
);
874 CHECK(ISC_R_NOMEMORY
);
876 memcpy(keyid
->secret
.base
, isc_buffer_base(&b
),
877 keyid
->secret
.length
);
878 ISC_LIST_APPEND(*keyids
, keyid
, link
);
880 result
= ISC_R_SUCCESS
;
884 free_controlkey(keyid
, mctx
);
886 cfg_obj_destroy(pctx
, &config
);
888 cfg_parser_destroy(&pctx
);
893 * Ensures that both '*global_keylistp' and '*control_keylistp' are
894 * valid or both are NULL.
897 get_key_info(cfg_obj_t
*config
, cfg_obj_t
*control
,
898 cfg_obj_t
**global_keylistp
, cfg_obj_t
**control_keylistp
)
901 cfg_obj_t
*control_keylist
= NULL
;
902 cfg_obj_t
*global_keylist
= NULL
;
904 REQUIRE(global_keylistp
!= NULL
&& *global_keylistp
== NULL
);
905 REQUIRE(control_keylistp
!= NULL
&& *control_keylistp
== NULL
);
907 control_keylist
= cfg_tuple_get(control
, "keys");
909 if (!cfg_obj_isvoid(control_keylist
) &&
910 cfg_list_first(control_keylist
) != NULL
) {
911 result
= cfg_map_get(config
, "key", &global_keylist
);
913 if (result
== ISC_R_SUCCESS
) {
914 *global_keylistp
= global_keylist
;
915 *control_keylistp
= control_keylist
;
921 update_listener(ns_controls_t
*cp
,
922 controllistener_t
**listenerp
, cfg_obj_t
*control
,
923 cfg_obj_t
*config
, isc_sockaddr_t
*addr
,
924 ns_aclconfctx_t
*aclconfctx
, const char *socktext
)
926 controllistener_t
*listener
;
928 cfg_obj_t
*global_keylist
= NULL
;
929 cfg_obj_t
*control_keylist
= NULL
;
930 dns_acl_t
*new_acl
= NULL
;
931 controlkeylist_t keys
;
932 isc_result_t result
= ISC_R_SUCCESS
;
934 for (listener
= ISC_LIST_HEAD(cp
->listeners
);
936 listener
= ISC_LIST_NEXT(listener
, link
))
937 if (isc_sockaddr_equal(addr
, &listener
->address
))
940 if (listener
== NULL
) {
946 * There is already a listener for this sockaddr.
947 * Update the access list and key information.
949 * First try to deal with the key situation. There are a few
951 * (a) It had an explicit keylist and still has an explicit keylist.
952 * (b) It had an automagic key and now has an explicit keylist.
953 * (c) It had an explicit keylist and now needs an automagic key.
954 * (d) It has an automagic key and still needs the automagic key.
956 * (c) and (d) are the annoying ones. The caller needs to know
957 * that it should use the automagic configuration for key information
958 * in place of the named.conf configuration.
960 * XXXDCL There is one other hazard that has not been dealt with,
961 * the problem that if a key change is being caused by a control
962 * channel reload, then the response will be with the new key
963 * and not able to be decrypted by the client.
966 get_key_info(config
, control
, &global_keylist
,
969 if (control_keylist
!= NULL
) {
970 INSIST(global_keylist
!= NULL
);
973 result
= controlkeylist_fromcfg(control_keylist
,
974 listener
->mctx
, &keys
);
975 if (result
== ISC_R_SUCCESS
) {
976 free_controlkeylist(&listener
->keys
, listener
->mctx
);
977 listener
->keys
= keys
;
978 register_keys(control
, global_keylist
, &listener
->keys
,
979 listener
->mctx
, socktext
);
982 free_controlkeylist(&listener
->keys
, listener
->mctx
);
983 result
= get_rndckey(listener
->mctx
, &listener
->keys
);
986 if (result
!= ISC_R_SUCCESS
&& global_keylist
!= NULL
)
988 * This message might be a little misleading since the
989 * "new keys" might in fact be identical to the old ones,
990 * but tracking whether they are identical just for the
991 * sake of avoiding this message would be too much trouble.
993 cfg_obj_log(control
, ns_g_lctx
, ISC_LOG_WARNING
,
994 "couldn't install new keys for "
995 "command channel %s: %s",
996 socktext
, isc_result_totext(result
));
1000 * Now, keep the old access list unless a new one can be made.
1002 if (control
!= NULL
) {
1003 allow
= cfg_tuple_get(control
, "allow");
1004 result
= ns_acl_fromconfig(allow
, config
, aclconfctx
,
1005 listener
->mctx
, &new_acl
);
1007 result
= dns_acl_any(listener
->mctx
, &new_acl
);
1010 if (result
== ISC_R_SUCCESS
) {
1011 dns_acl_detach(&listener
->acl
);
1012 dns_acl_attach(new_acl
, &listener
->acl
);
1013 dns_acl_detach(&new_acl
);
1015 /* XXXDCL say the old acl is still used? */
1016 cfg_obj_log(control
, ns_g_lctx
, ISC_LOG_WARNING
,
1017 "couldn't install new acl for "
1018 "command channel %s: %s",
1019 socktext
, isc_result_totext(result
));
1021 *listenerp
= listener
;
1025 add_listener(ns_controls_t
*cp
, controllistener_t
**listenerp
,
1026 cfg_obj_t
*control
, cfg_obj_t
*config
, isc_sockaddr_t
*addr
,
1027 ns_aclconfctx_t
*aclconfctx
, const char *socktext
)
1029 isc_mem_t
*mctx
= cp
->server
->mctx
;
1030 controllistener_t
*listener
;
1032 cfg_obj_t
*global_keylist
= NULL
;
1033 cfg_obj_t
*control_keylist
= NULL
;
1034 dns_acl_t
*new_acl
= NULL
;
1035 isc_result_t result
= ISC_R_SUCCESS
;
1037 listener
= isc_mem_get(mctx
, sizeof(*listener
));
1038 if (listener
== NULL
)
1039 result
= ISC_R_NOMEMORY
;
1041 if (result
== ISC_R_SUCCESS
) {
1042 listener
->controls
= cp
;
1043 listener
->mctx
= mctx
;
1044 listener
->task
= cp
->server
->task
;
1045 listener
->address
= *addr
;
1046 listener
->sock
= NULL
;
1047 listener
->listening
= ISC_FALSE
;
1048 listener
->exiting
= ISC_FALSE
;
1049 listener
->acl
= NULL
;
1050 ISC_LINK_INIT(listener
, link
);
1051 ISC_LIST_INIT(listener
->keys
);
1052 ISC_LIST_INIT(listener
->connections
);
1057 if (control
!= NULL
) {
1058 allow
= cfg_tuple_get(control
, "allow");
1059 result
= ns_acl_fromconfig(allow
, config
, aclconfctx
,
1062 result
= dns_acl_any(mctx
, &new_acl
);
1066 if (result
== ISC_R_SUCCESS
) {
1067 dns_acl_attach(new_acl
, &listener
->acl
);
1068 dns_acl_detach(&new_acl
);
1071 get_key_info(config
, control
, &global_keylist
,
1074 if (control_keylist
!= NULL
) {
1075 result
= controlkeylist_fromcfg(control_keylist
,
1078 if (result
== ISC_R_SUCCESS
)
1079 register_keys(control
, global_keylist
,
1081 listener
->mctx
, socktext
);
1083 result
= get_rndckey(mctx
, &listener
->keys
);
1085 if (result
!= ISC_R_SUCCESS
&& control
!= NULL
)
1086 cfg_obj_log(control
, ns_g_lctx
, ISC_LOG_WARNING
,
1087 "couldn't install keys for "
1088 "command channel %s: %s",
1089 socktext
, isc_result_totext(result
));
1092 if (result
== ISC_R_SUCCESS
) {
1093 int pf
= isc_sockaddr_pf(&listener
->address
);
1094 if ((pf
== AF_INET
&& isc_net_probeipv4() != ISC_R_SUCCESS
) ||
1095 (pf
== AF_INET6
&& isc_net_probeipv6() != ISC_R_SUCCESS
))
1096 result
= ISC_R_FAMILYNOSUPPORT
;
1099 if (result
== ISC_R_SUCCESS
)
1100 result
= isc_socket_create(ns_g_socketmgr
,
1101 isc_sockaddr_pf(&listener
->address
),
1105 if (result
== ISC_R_SUCCESS
)
1106 result
= isc_socket_bind(listener
->sock
,
1107 &listener
->address
);
1109 if (result
== ISC_R_SUCCESS
)
1110 result
= control_listen(listener
);
1112 if (result
== ISC_R_SUCCESS
)
1113 result
= control_accept(listener
);
1115 if (result
== ISC_R_SUCCESS
) {
1116 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1117 NS_LOGMODULE_CONTROL
, ISC_LOG_NOTICE
,
1118 "command channel listening on %s", socktext
);
1119 *listenerp
= listener
;
1122 if (listener
!= NULL
) {
1123 listener
->exiting
= ISC_TRUE
;
1124 free_listener(listener
);
1127 if (control
!= NULL
)
1128 cfg_obj_log(control
, ns_g_lctx
, ISC_LOG_WARNING
,
1129 "couldn't add command channel %s: %s",
1130 socktext
, isc_result_totext(result
));
1132 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1133 NS_LOGMODULE_CONTROL
, ISC_LOG_NOTICE
,
1134 "couldn't add command channel %s: %s",
1135 socktext
, isc_result_totext(result
));
1140 /* XXXDCL return error results? fail hard? */
1144 ns_controls_configure(ns_controls_t
*cp
, cfg_obj_t
*config
,
1145 ns_aclconfctx_t
*aclconfctx
)
1147 controllistener_t
*listener
;
1148 controllistenerlist_t new_listeners
;
1149 cfg_obj_t
*controlslist
= NULL
;
1150 cfg_listelt_t
*element
, *element2
;
1151 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
1153 ISC_LIST_INIT(new_listeners
);
1156 * Get the list of named.conf 'controls' statements.
1158 (void)cfg_map_get(config
, "controls", &controlslist
);
1161 * Run through the new control channel list, noting sockets that
1162 * are already being listened on and moving them to the new list.
1164 * Identifying duplicate addr/port combinations is left to either
1165 * the underlying config code, or to the bind attempt getting an
1166 * address-in-use error.
1168 if (controlslist
!= NULL
) {
1169 for (element
= cfg_list_first(controlslist
);
1171 element
= cfg_list_next(element
)) {
1172 cfg_obj_t
*controls
;
1173 cfg_obj_t
*inetcontrols
= NULL
;
1175 controls
= cfg_listelt_value(element
);
1176 (void)cfg_map_get(controls
, "inet", &inetcontrols
);
1177 if (inetcontrols
== NULL
)
1180 for (element2
= cfg_list_first(inetcontrols
);
1182 element2
= cfg_list_next(element2
)) {
1185 isc_sockaddr_t
*addr
;
1188 * The parser handles BIND 8 configuration file
1189 * syntax, so it allows unix phrases as well
1190 * inet phrases with no keys{} clause.
1192 * "unix" phrases have been reported as
1193 * unsupported by the parser.
1195 control
= cfg_listelt_value(element2
);
1197 obj
= cfg_tuple_get(control
, "address");
1198 addr
= cfg_obj_assockaddr(obj
);
1199 if (isc_sockaddr_getport(addr
) == 0)
1200 isc_sockaddr_setport(addr
,
1203 isc_sockaddr_format(addr
, socktext
,
1206 isc_log_write(ns_g_lctx
,
1207 NS_LOGCATEGORY_GENERAL
,
1208 NS_LOGMODULE_CONTROL
,
1210 "processing control channel %s",
1213 update_listener(cp
, &listener
, control
, config
,
1214 addr
, aclconfctx
, socktext
);
1216 if (listener
!= NULL
)
1218 * Remove the listener from the old
1219 * list, so it won't be shut down.
1221 ISC_LIST_UNLINK(cp
->listeners
,
1225 * This is a new listener.
1227 add_listener(cp
, &listener
, control
,
1228 config
, addr
, aclconfctx
,
1231 if (listener
!= NULL
)
1232 ISC_LIST_APPEND(new_listeners
,
1239 for (i
= 0; i
< 2; i
++) {
1240 isc_sockaddr_t addr
;
1243 struct in_addr localhost
;
1245 if (isc_net_probeipv4() != ISC_R_SUCCESS
)
1247 localhost
.s_addr
= htonl(INADDR_LOOPBACK
);
1248 isc_sockaddr_fromin(&addr
, &localhost
, 0);
1250 if (isc_net_probeipv6() != ISC_R_SUCCESS
)
1252 isc_sockaddr_fromin6(&addr
,
1253 &in6addr_loopback
, 0);
1255 isc_sockaddr_setport(&addr
, NS_CONTROL_PORT
);
1257 isc_sockaddr_format(&addr
, socktext
, sizeof(socktext
));
1259 update_listener(cp
, &listener
, NULL
, NULL
,
1260 &addr
, NULL
, socktext
);
1262 if (listener
!= NULL
)
1264 * Remove the listener from the old
1265 * list, so it won't be shut down.
1267 ISC_LIST_UNLINK(cp
->listeners
,
1271 * This is a new listener.
1273 add_listener(cp
, &listener
, NULL
, NULL
,
1274 &addr
, NULL
, socktext
);
1276 if (listener
!= NULL
)
1277 ISC_LIST_APPEND(new_listeners
,
1283 * ns_control_shutdown() will stop whatever is on the global
1284 * listeners list, which currently only has whatever sockaddrs
1285 * were in the previous configuration (if any) that do not
1286 * remain in the current configuration.
1288 controls_shutdown(cp
);
1291 * Put all of the valid listeners on the listeners list.
1292 * Anything already on listeners in the process of shutting
1293 * down will be taken care of by listen_done().
1295 ISC_LIST_APPENDLIST(cp
->listeners
, new_listeners
, link
);
1296 return (ISC_R_SUCCESS
);
1300 ns_controls_create(ns_server_t
*server
, ns_controls_t
**ctrlsp
) {
1301 isc_mem_t
*mctx
= server
->mctx
;
1302 isc_result_t result
;
1303 ns_controls_t
*controls
= isc_mem_get(mctx
, sizeof(*controls
));
1305 if (controls
== NULL
)
1306 return (ISC_R_NOMEMORY
);
1307 controls
->server
= server
;
1308 ISC_LIST_INIT(controls
->listeners
);
1309 controls
->shuttingdown
= ISC_FALSE
;
1310 controls
->symtab
= NULL
;
1311 result
= isccc_cc_createsymtab(&controls
->symtab
);
1312 if (result
!= ISC_R_SUCCESS
) {
1313 isc_mem_put(server
->mctx
, controls
, sizeof(*controls
));
1317 return (ISC_R_SUCCESS
);
1321 ns_controls_destroy(ns_controls_t
**ctrlsp
) {
1322 ns_controls_t
*controls
= *ctrlsp
;
1324 REQUIRE(ISC_LIST_EMPTY(controls
->listeners
));
1326 isccc_symtab_destroy(&controls
->symtab
);
1327 isc_mem_put(controls
->server
->mctx
, controls
, sizeof(*controls
));