xref: /openbsd-src/usr.sbin/radiusd/radiusd.c (revision abc3a9caf406707c5ef3c80adcf491e5111b4294)
1 /*	$OpenBSD: radiusd.c,v 1.62 2025/01/29 10:12:22 yasuoka Exp $	*/
2 
3 /*
4  * Copyright (c) 2013, 2023 Internet Initiative Japan Inc.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <sys/queue.h>
23 #include <sys/socket.h>
24 #include <sys/time.h>
25 #include <sys/uio.h>
26 #include <sys/wait.h>
27 
28 #include <err.h>
29 #include <errno.h>
30 #include <event.h>
31 #include <fcntl.h>
32 #include <fnmatch.h>
33 #include <imsg.h>
34 #include <netdb.h>
35 #include <paths.h>
36 #include <pwd.h>
37 #include <signal.h>
38 #include <stdbool.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <syslog.h>
43 #include <unistd.h>
44 
45 #include <radius.h>
46 
47 #include "radiusd.h"
48 #include "radiusd_local.h"
49 #include "radius_subr.h"
50 #include "log.h"
51 #include "util.h"
52 #include "imsg_subr.h"
53 #include "control.h"
54 
55 static int		 radiusd_start(struct radiusd *);
56 static void		 radiusd_stop(struct radiusd *);
57 static void		 radiusd_free(struct radiusd *);
58 static void		 radiusd_listen_on_event(int, short, void *);
59 static void		 radiusd_listen_handle_packet(struct radiusd_listen *,
60 			    RADIUS_PACKET *, struct sockaddr *, socklen_t);
61 static void		 radiusd_on_sigterm(int, short, void *);
62 static void		 radiusd_on_sigint(int, short, void *);
63 static void		 radiusd_on_sighup(int, short, void *);
64 static void		 radiusd_on_sigchld(int, short, void *);
65 static void		 raidus_query_access_request(struct radius_query *);
66 static void		 radius_query_access_response(struct radius_query *);
67 static void		 raidus_query_accounting_request(
68 			    struct radiusd_accounting *, struct radius_query *);
69 static void		 radius_query_accounting_response(
70 			    struct radius_query *);
71 static const char	*radius_query_client_secret(struct radius_query *);
72 static const char	*radius_code_string(int);
73 static const char	*radius_acct_status_type_string(uint32_t);
74 static int		 radiusd_access_response_fixup(struct radius_query *,
75 			    struct radius_query *, bool);
76 static void		 radiusd_module_reset_ev_handler(
77 			    struct radiusd_module *);
78 static int		 radiusd_module_imsg_read(struct radiusd_module *);
79 static void		 radiusd_module_imsg(struct radiusd_module *,
80 			    struct imsg *);
81 
82 static struct radiusd_module_radpkt_arg *
83 			 radiusd_module_recv_radpkt(struct radiusd_module *,
84 			    struct imsg *, uint32_t, const char *);
85 static void		 radiusd_module_on_imsg_io(int, short, void *);
86 static void		 radiusd_module_start(struct radiusd_module *);
87 static void		 radiusd_module_stop(struct radiusd_module *);
88 static void		 radiusd_module_close(struct radiusd_module *);
89 static void		 radiusd_module_userpass(struct radiusd_module *,
90 			    struct radius_query *);
91 static void		 radiusd_module_access_request(struct radiusd_module *,
92 			    struct radius_query *);
93 static void		 radiusd_module_next_response(struct radiusd_module *,
94 			    struct radius_query *, RADIUS_PACKET *);
95 static void		 radiusd_module_request_decoration(
96 			    struct radiusd_module *, struct radius_query *);
97 static void		 radiusd_module_response_decoration(
98 			    struct radiusd_module *, struct radius_query *);
99 static void		 radiusd_module_account_request(struct radiusd_module *,
100 			    struct radius_query *);
101 static int		 imsg_compose_radius_packet(struct imsgbuf *,
102 			    uint32_t, u_int, RADIUS_PACKET *);
103 static void		 close_stdio(void);
104 
105 static u_int		 radius_query_id_seq = 0;
106 int			 debug = 0;
107 struct radiusd		*radiusd_s = NULL;
108 
109 static __dead void
110 usage(void)
111 {
112 	extern char *__progname;
113 
114 	fprintf(stderr, "usage: %s [-dn] [-f file]\n", __progname);
115 	exit(EXIT_FAILURE);
116 }
117 
118 int
119 main(int argc, char *argv[])
120 {
121 	extern char		*__progname;
122 	const char		*conffile = CONFFILE;
123 	int			 ch, error;
124 	struct radiusd		*radiusd;
125 	bool			 noaction = false;
126 	struct passwd		*pw;
127 
128 	while ((ch = getopt(argc, argv, "df:n")) != -1)
129 		switch (ch) {
130 		case 'd':
131 			debug++;
132 			break;
133 
134 		case 'f':
135 			conffile = optarg;
136 			break;
137 
138 		case 'n':
139 			noaction = true;
140 			break;
141 
142 		default:
143 			usage();
144 			/* NOTREACHED */
145 		}
146 
147 	argc -= optind;
148 	argv += optind;
149 
150 	if (argc != 0)
151 		usage();
152 
153 	if ((radiusd = calloc(1, sizeof(*radiusd))) == NULL)
154 		err(1, "calloc");
155 	radiusd_s = radiusd;
156 	TAILQ_INIT(&radiusd->listen);
157 	TAILQ_INIT(&radiusd->query);
158 
159 	if (!noaction && debug == 0)
160 		daemon(0, 1);	/* pend closing stdio files */
161 
162 	if (parse_config(conffile, radiusd) != 0)
163 		errx(EXIT_FAILURE, "config error");
164 	log_init(debug);
165 	if (noaction) {
166 		fprintf(stderr, "configuration OK\n");
167 		exit(EXIT_SUCCESS);
168 	}
169 
170 	if (debug == 0)
171 		close_stdio(); /* close stdio files now */
172 
173 	if (control_init(RADIUSD_SOCK) == -1)
174 		exit(EXIT_FAILURE);
175 
176 	event_init();
177 
178 	if ((pw = getpwnam(RADIUSD_USER)) == NULL)
179 		errx(EXIT_FAILURE, "user `%s' is not found in password "
180 		    "database", RADIUSD_USER);
181 
182 	if (chroot(pw->pw_dir) == -1)
183 		err(EXIT_FAILURE, "chroot");
184 	if (chdir("/") == -1)
185 		err(EXIT_FAILURE, "chdir(\"/\")");
186 
187 	if (setgroups(1, &pw->pw_gid) ||
188 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
189 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
190 		err(EXIT_FAILURE, "cannot drop privileges");
191 
192 	signal(SIGPIPE, SIG_IGN);
193 	openlog(NULL, LOG_PID, LOG_DAEMON);
194 
195 	signal_set(&radiusd->ev_sigterm, SIGTERM, radiusd_on_sigterm, radiusd);
196 	signal_set(&radiusd->ev_sigint,  SIGINT,  radiusd_on_sigint,  radiusd);
197 	signal_set(&radiusd->ev_sighup,  SIGHUP,  radiusd_on_sighup,  radiusd);
198 	signal_set(&radiusd->ev_sigchld, SIGCHLD, radiusd_on_sigchld, radiusd);
199 
200 	if (radiusd_start(radiusd) != 0)
201 		errx(EXIT_FAILURE, "start failed");
202 	if (control_listen() == -1)
203 		exit(EXIT_FAILURE);
204 
205 	if (pledge("stdio inet", NULL) == -1)
206 		err(EXIT_FAILURE, "pledge");
207 
208 	event_loop(0);
209 
210 	if (radiusd->error != 0)
211 		log_warnx("exiting on error");
212 
213 	radiusd_stop(radiusd);
214 	control_cleanup();
215 
216 	event_loop(0);
217 
218 	error = radiusd->error;
219 	radiusd_free(radiusd);
220 	event_base_free(NULL);
221 
222 	if (error != 0)
223 		exit(EXIT_FAILURE);
224 	else
225 		exit(EXIT_SUCCESS);
226 }
227 
228 static int
229 radiusd_start(struct radiusd *radiusd)
230 {
231 	struct radiusd_listen	*l;
232 	struct radiusd_module	*module;
233 	int			 s, on;
234 	char			 hbuf[NI_MAXHOST];
235 
236 	TAILQ_FOREACH(l, &radiusd->listen, next) {
237 		if (getnameinfo(
238 		    (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len,
239 		    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) {
240 			log_warn("%s: getnameinfo()", __func__);
241 			goto on_error;
242 		}
243 		if ((s = socket(l->addr.ipv4.sin_family,
244 		    l->stype | SOCK_NONBLOCK, l->sproto)) == -1) {
245 			log_warn("Listen %s port %d is failed: socket()",
246 			    hbuf, (int)htons(l->addr.ipv4.sin_port));
247 			goto on_error;
248 		}
249 
250 		on = 1;
251 		if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
252 		    == -1)
253 			log_warn("%s: setsockopt(,,SO_REUSEADDR) failed: %m",
254 			    __func__);
255 		if (bind(s, (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len)
256 		    != 0) {
257 			log_warn("Listen %s port %d is failed: bind()",
258 			    hbuf, (int)htons(l->addr.ipv4.sin_port));
259 			close(s);
260 			goto on_error;
261 		}
262 		if (l->addr.ipv4.sin_family == AF_INET)
263 			log_info("Start listening on %s:%d/udp", hbuf,
264 			    (int)ntohs(l->addr.ipv4.sin_port));
265 		else
266 			log_info("Start listening on [%s]:%d/udp", hbuf,
267 			    (int)ntohs(l->addr.ipv4.sin_port));
268 		event_set(&l->ev, s, EV_READ | EV_PERSIST,
269 		    radiusd_listen_on_event, l);
270 		if (event_add(&l->ev, NULL) != 0) {
271 			log_warn("event_add() failed at %s()", __func__);
272 			close(s);
273 			goto on_error;
274 		}
275 		l->sock = s;
276 		l->radiusd = radiusd;
277 	}
278 
279 	signal_add(&radiusd->ev_sigterm, NULL);
280 	signal_add(&radiusd->ev_sigint, NULL);
281 	signal_add(&radiusd->ev_sighup, NULL);
282 	signal_add(&radiusd->ev_sigchld, NULL);
283 
284 	TAILQ_FOREACH(module, &radiusd->module, next) {
285 		if (debug > 0)
286 			radiusd_module_set(module, "_debug", 0, NULL);
287 		radiusd_module_start(module);
288 	}
289 
290 	return (0);
291 on_error:
292 	radiusd->error++;
293 	event_loopbreak();
294 
295 	return (-1);
296 }
297 
298 static void
299 radiusd_stop(struct radiusd *radiusd)
300 {
301 	char			 hbuf[NI_MAXHOST];
302 	struct radiusd_listen	*l;
303 	struct radiusd_module	*module;
304 
305 	TAILQ_FOREACH_REVERSE(l, &radiusd->listen, radiusd_listen_head, next) {
306 		if (l->sock >= 0) {
307 			if (getnameinfo(
308 			    (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len,
309 			    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
310 				strlcpy(hbuf, "error", sizeof(hbuf));
311 			if (l->addr.ipv4.sin_family == AF_INET)
312 				log_info("Stop listening on %s:%d/udp", hbuf,
313 				    (int)ntohs(l->addr.ipv4.sin_port));
314 			else
315 				log_info("Stop listening on [%s]:%d/udp", hbuf,
316 				    (int)ntohs(l->addr.ipv4.sin_port));
317 			event_del(&l->ev);
318 			close(l->sock);
319 		}
320 		l->sock = -1;
321 	}
322 	TAILQ_FOREACH(module, &radiusd->module, next) {
323 		radiusd_module_stop(module);
324 		radiusd_module_close(module);
325 	}
326 	if (signal_pending(&radiusd->ev_sigterm, NULL))
327 		signal_del(&radiusd->ev_sigterm);
328 	if (signal_pending(&radiusd->ev_sigint, NULL))
329 		signal_del(&radiusd->ev_sigint);
330 	if (signal_pending(&radiusd->ev_sighup, NULL))
331 		signal_del(&radiusd->ev_sighup);
332 	if (signal_pending(&radiusd->ev_sigchld, NULL))
333 		signal_del(&radiusd->ev_sigchld);
334 }
335 
336 static void
337 radiusd_free(struct radiusd *radiusd)
338 {
339 	int				 i;
340 	struct radiusd_listen		*listn, *listnt;
341 	struct radiusd_client		*client, *clientt;
342 	struct radiusd_module		*module, *modulet;
343 	struct radiusd_module_ref	*modref, *modreft;
344 	struct radiusd_authentication	*authen, *authent;
345 	struct radiusd_accounting	*acct, *acctt;
346 
347 	TAILQ_FOREACH_SAFE(authen, &radiusd->authen, next, authent) {
348 		TAILQ_REMOVE(&radiusd->authen, authen, next);
349 		free(authen->auth);
350 		TAILQ_FOREACH_SAFE(modref, &authen->deco, next, modreft) {
351 			TAILQ_REMOVE(&authen->deco, modref, next);
352 			free(modref);
353 		}
354 		for (i = 0; authen->username[i] != NULL; i++)
355 			free(authen->username[i]);
356 		free(authen->username);
357 		free(authen);
358 	}
359 	TAILQ_FOREACH_SAFE(acct, &radiusd->account, next, acctt) {
360 		TAILQ_REMOVE(&radiusd->account, acct, next);
361 		free(acct->secret);
362 		free(acct->acct);
363 		TAILQ_FOREACH_SAFE(modref, &acct->deco, next, modreft) {
364 			TAILQ_REMOVE(&acct->deco, modref, next);
365 			free(modref);
366 		}
367 		for (i = 0; acct->username[i] != NULL; i++)
368 			free(acct->username[i]);
369 		free(acct->username);
370 		free(acct);
371 	}
372 	TAILQ_FOREACH_SAFE(module, &radiusd->module, next, modulet) {
373 		TAILQ_REMOVE(&radiusd->module, module, next);
374 		radiusd_module_unload(module);
375 	}
376 	TAILQ_FOREACH_SAFE(client, &radiusd->client, next, clientt) {
377 		TAILQ_REMOVE(&radiusd->client, client, next);
378 		explicit_bzero(client->secret, sizeof(client->secret));
379 		free(client);
380 	}
381 	TAILQ_FOREACH_SAFE(listn, &radiusd->listen, next, listnt) {
382 		TAILQ_REMOVE(&radiusd->listen, listn, next);
383 		free(listn);
384 	}
385 	free(radiusd);
386 }
387 
388 /***********************************************************************
389  * Network event handlers
390  ***********************************************************************/
391 #define IPv4_cmp(_in, _addr, _mask) (				\
392 	((_in)->s_addr & (_mask)->addr.ipv4.s_addr) ==		\
393 	    (_addr)->addr.ipv4.s_addr)
394 #define	s6_addr32(_in6)	((uint32_t *)(_in6)->s6_addr)
395 #define IPv6_cmp(_in6, _addr, _mask) (				\
396 	((s6_addr32(_in6)[3] & (_mask)->addr.addr32[3])		\
397 	    == (_addr)->addr.addr32[3]) &&			\
398 	((s6_addr32(_in6)[2] & (_mask)->addr.addr32[2])		\
399 	    == (_addr)->addr.addr32[2]) &&			\
400 	((s6_addr32(_in6)[1] & (_mask)->addr.addr32[1])		\
401 	    == (_addr)->addr.addr32[1]) &&			\
402 	((s6_addr32(_in6)[0] & (_mask)->addr.addr32[0])		\
403 	    == (_addr)->addr.addr32[0]))
404 
405 static void
406 radiusd_listen_on_event(int fd, short evmask, void *ctx)
407 {
408 	int				 sz;
409 	RADIUS_PACKET			*packet = NULL;
410 	struct sockaddr_storage		 peer;
411 	socklen_t			 peersz;
412 	struct radiusd_listen		*listn = ctx;
413 	static u_char			 buf[65535];
414 
415 	if (evmask & EV_READ) {
416 		peersz = sizeof(peer);
417 		if ((sz = recvfrom(listn->sock, buf, sizeof(buf), 0,
418 		    (struct sockaddr *)&peer, &peersz)) == -1) {
419 			if (errno == EAGAIN)
420 				return;
421 			log_warn("%s: recvfrom() failed", __func__);
422 			return;
423 		}
424 		RADIUSD_ASSERT(peer.ss_family == AF_INET ||
425 		    peer.ss_family == AF_INET6);
426 		if ((packet = radius_convert_packet(buf, sz)) == NULL)
427 			log_warn("%s: radius_convert_packet() failed",
428 			    __func__);
429 		else
430 			radiusd_listen_handle_packet(listn, packet,
431 			    (struct sockaddr *)&peer, peersz);
432 	}
433 }
434 
435 static void
436 radiusd_listen_handle_packet(struct radiusd_listen *listn,
437     RADIUS_PACKET *packet, struct sockaddr *peer, socklen_t peerlen)
438 {
439 	int				 i, req_id, req_code;
440 	static char			 username[256];
441 	char				 peerstr[NI_MAXHOST + NI_MAXSERV + 30];
442 	struct radiusd_authentication	*authen;
443 	struct radiusd_accounting	*accounting;
444 	struct radiusd_client		*client;
445 	struct radius_query		*q = NULL;
446 	uint32_t			 acct_status;
447 #define in(_x)	(((struct sockaddr_in  *)_x)->sin_addr)
448 #define in6(_x)	(((struct sockaddr_in6 *)_x)->sin6_addr)
449 
450 	req_id = radius_get_id(packet);
451 	req_code = radius_get_code(packet);
452 	/* prepare some information about this messages */
453 	if (addrport_tostring(peer, peerlen, peerstr, sizeof(peerstr)) ==
454 	    NULL) {
455 		log_warn("%s: getnameinfo() failed", __func__);
456 		goto on_error;
457 	}
458 
459 	/*
460 	 * Find a matching `client' entry
461 	 */
462 	TAILQ_FOREACH(client, &listn->radiusd->client, next) {
463 		if (client->af != peer->sa_family)
464 			continue;
465 		if (peer->sa_family == AF_INET && IPv4_cmp(
466 		    &in(peer), &client->addr, &client->mask))
467 			break;
468 		else if (peer->sa_family == AF_INET6 && IPv6_cmp(
469 		    &in6(peer), &client->addr, &client->mask))
470 			break;
471 	}
472 	if (client == NULL) {
473 		log_warnx("Received %s(code=%d) from %s id=%d: no `client' "
474 		    "matches", radius_code_string(req_code), req_code, peerstr,
475 		    req_id);
476 		goto on_error;
477 	}
478 
479 	/* Check the request authenticator if accounting */
480 	if (req_code == RADIUS_CODE_ACCOUNTING_REQUEST &&
481 	    radius_check_accounting_request_authenticator(packet,
482 	    client->secret) != 0) {
483 		log_warnx("Received %s(code=%d) from %s id=%d: bad request "
484 		    "authenticator", radius_code_string(req_code), req_code,
485 		    peerstr, req_id);
486 		goto on_error;
487 	}
488 
489 	/* Check the client's Message-Authenticator */
490 	if (client->msgauth_required && !listn->accounting &&
491 	    !radius_has_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) {
492 		log_warnx("Received %s(code=%d) from %s id=%d: no message "
493 		    "authenticator", radius_code_string(req_code), req_code,
494 		    peerstr, req_id);
495 		goto on_error;
496 	}
497 
498 	if (radius_has_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR) &&
499 	    radius_check_message_authenticator(packet, client->secret) != 0) {
500 		log_warnx("Received %s(code=%d) from %s id=%d: bad message "
501 		    "authenticator", radius_code_string(req_code), req_code,
502 		    peerstr, req_id);
503 		goto on_error;
504 	}
505 
506 	/*
507 	 * Find a duplicate request.  In RFC 2865, it has the same source IP
508 	 * address and source UDP port and Identifier.
509 	 */
510 	TAILQ_FOREACH(q, &listn->radiusd->query, next) {
511 		if (peer->sa_family == q->clientaddr.ss_family &&
512 		    ((peer->sa_family == AF_INET && in(&q->clientaddr).s_addr ==
513 		    in(peer).s_addr) || (peer->sa_family == AF_INET6 &&
514 		    IN6_ARE_ADDR_EQUAL(&in6(&q->clientaddr), &in6(peer)))) &&
515 		    ((struct sockaddr_in *)&q->clientaddr)->sin_port ==
516 		    ((struct sockaddr_in *)peer)->sin_port &&
517 		    req_id == q->req_id)
518 			break;	/* found it */
519 	}
520 	if (q != NULL) {
521 		log_info("Received %s(code=%d) from %s id=%d: duplicated "
522 		    "with q=%u", radius_code_string(req_code), req_code,
523 		    peerstr, req_id, q->id);
524 		q = NULL;
525 		goto on_error;
526 	}
527 
528 	if ((q = calloc(1, sizeof(struct radius_query))) == NULL) {
529 		log_warn("%s: Out of memory", __func__);
530 		goto on_error;
531 	}
532 	if (radius_get_string_attr(packet, RADIUS_TYPE_USER_NAME, username,
533 	    sizeof(username)) != 0) {
534 		log_info("Received %s(code=%d) from %s id=%d: no User-Name "
535 		    "attribute", radius_code_string(req_code), req_code,
536 		    peerstr, req_id);
537 	} else
538 		strlcpy(q->username, username, sizeof(q->username));
539 
540 	q->id = ++radius_query_id_seq;
541 	q->radiusd = listn->radiusd;
542 	q->clientaddrlen = peerlen;
543 	memcpy(&q->clientaddr, peer, peerlen);
544 	q->listen = listn;
545 	q->req = packet;
546 	q->client = client;
547 	q->req_id = req_id;
548 	radius_get_authenticator(packet, q->req_auth);
549 	packet = NULL;
550 	TAILQ_INSERT_TAIL(&listn->radiusd->query, q, next);
551 
552 	switch (req_code) {
553 	case RADIUS_CODE_ACCESS_REQUEST:
554 		if (listn->accounting) {
555 			log_info("Received %s(code=%d) from %s id=%d: "
556 			    "ignored because the port is for authentication",
557 			    radius_code_string(req_code), req_code, peerstr,
558 			    req_id);
559 			break;
560 		}
561 		/*
562 		 * Find a matching `authenticate' entry
563 		 */
564 		TAILQ_FOREACH(authen, &listn->radiusd->authen, next) {
565 			for (i = 0; authen->username[i] != NULL; i++) {
566 				if (fnmatch(authen->username[i], username, 0)
567 				    == 0)
568 					goto found;
569 			}
570 		}
571  found:
572 		if (authen == NULL) {
573 			log_warnx("Received %s(code=%d) from %s id=%d "
574 			    "username=%s: no `authenticate' matches.",
575 			    radius_code_string(req_code), req_code, peerstr,
576 			    req_id, username);
577 			goto on_error;
578 		}
579 		q->authen = authen;
580 
581 		if (!MODULE_DO_USERPASS(authen->auth->module) &&
582 		    !MODULE_DO_ACCSREQ(authen->auth->module)) {
583 			log_warnx("Received %s(code=%d) from %s id=%d "
584 			    "username=%s: module `%s' is not running.",
585 			    radius_code_string(req_code), req_code, peerstr,
586 			    req_id, username, authen->auth->module->name);
587 			goto on_error;
588 		}
589 
590 		log_info("Received %s(code=%d) from %s id=%d username=%s "
591 		    "q=%u: `%s' authentication is starting",
592 		    radius_code_string(req_code), req_code, peerstr, q->req_id,
593 		    q->username, q->id, q->authen->auth->module->name);
594 
595 		raidus_query_access_request(q);
596 		return;
597 	case RADIUS_CODE_ACCOUNTING_REQUEST:
598 		if (!listn->accounting) {
599 			log_info("Received %s(code=%d) from %s id=%d: "
600 			    "ignored because the port is for accounting",
601 			    radius_code_string(req_code), req_code, peerstr,
602 			    req_id);
603 			break;
604 		}
605 		if (radius_get_uint32_attr(q->req, RADIUS_TYPE_ACCT_STATUS_TYPE,
606 		    &acct_status) != 0)
607 			acct_status = 0;
608 		/*
609 		 * Find a matching `accounting' entry
610 		 */
611 		TAILQ_FOREACH(accounting, &listn->radiusd->account, next) {
612 			if (acct_status == RADIUS_ACCT_STATUS_TYPE_ACCT_ON ||
613 			    acct_status == RADIUS_ACCT_STATUS_TYPE_ACCT_OFF) {
614 				raidus_query_accounting_request(accounting, q);
615 				continue;
616 			}
617 			for (i = 0; accounting->username[i] != NULL; i++) {
618 				if (fnmatch(accounting->username[i], username,
619 				    0) == 0)
620 					break;
621 			}
622 			if (accounting->username[i] == NULL)
623 				continue;
624 			raidus_query_accounting_request(accounting, q);
625 			if (accounting->quick)
626 				break;
627 		}
628 		/* pass NULL to hadnle this self without module */
629 		raidus_query_accounting_request(NULL, q);
630 
631 		if ((q->res = radius_new_response_packet(
632 		    RADIUS_CODE_ACCOUNTING_RESPONSE, q->req)) == NULL)
633 			log_warn("%s: radius_new_response_packet() failed",
634 			    __func__);
635 		else
636 			radius_query_accounting_response(q);
637 		break;
638 	default:
639 		log_info("Received %s(code=%d) from %s id=%d: %s is not "
640 		    "supported in this implementation", radius_code_string(
641 		    req_code), req_code, peerstr, req_id, radius_code_string(
642 		    req_code));
643 		break;
644 	}
645 on_error:
646 	if (packet != NULL)
647 		radius_delete_packet(packet);
648 	if (q != NULL)
649 		radiusd_access_request_aborted(q);
650 #undef in
651 #undef in6
652 }
653 
654 static void
655 raidus_query_access_request(struct radius_query *q)
656 {
657 	struct radiusd_authentication	*authen = q->authen;
658 
659 	/* first or next request decoration */
660 	for (;;) {
661 		if (q->deco == NULL)
662 			q->deco = TAILQ_FIRST(&q->authen->deco);
663 		else
664 			q->deco = TAILQ_NEXT(q->deco, next);
665 		if (q->deco == NULL || MODULE_DO_REQDECO(q->deco->module))
666 			break;
667 	}
668 
669 	if (q->deco != NULL)
670 		radiusd_module_request_decoration(q->deco->module, q);
671 	else {
672 		RADIUSD_ASSERT(authen->auth != NULL);
673 		if (MODULE_DO_ACCSREQ(authen->auth->module))
674 			radiusd_module_access_request(authen->auth->module, q);
675 		else if (MODULE_DO_USERPASS(authen->auth->module))
676 			radiusd_module_userpass(authen->auth->module, q);
677 	}
678 }
679 
680 static void
681 radius_query_access_response(struct radius_query *q)
682 {
683 	int			 sz, res_id, res_code;
684 	char			 buf[NI_MAXHOST + NI_MAXSERV + 30];
685 	struct radius_query	*q_last, *q0;
686 
687 	q_last = q;
688  next:
689 	/* first or next response decoration */
690 	for (;;) {
691 		if (q->deco == NULL)
692 			q->deco = TAILQ_FIRST(&q->authen->deco);
693 		else
694 			q->deco = TAILQ_NEXT(q->deco, next);
695 		if (q->deco == NULL || MODULE_DO_RESDECO(q->deco->module))
696 			break;
697 	}
698 
699 	if (q->deco != NULL) {
700 		radiusd_module_response_decoration(q->deco->module, q);
701 		return;
702 	}
703 
704 	if (q->prev != NULL) {
705 		if (MODULE_DO_NEXTRES(q->prev->authen->auth->module)) {
706 			if (radiusd_access_response_fixup(q->prev, q_last, 0)
707 			    != 0)
708 				goto on_error;
709 			q0 = q;
710 			q = q->prev;
711 			/* dissolve the relation */
712 			q0->prev = NULL;
713 			q->hasnext = false;
714 			radiusd_module_next_response(q->authen->auth->module,
715 			    q, q_last->res);
716 			radiusd_access_request_aborted(q0);
717 			return;
718 		}
719 		q = q->prev;
720 		goto next;
721 	}
722 
723 	if (radiusd_access_response_fixup(q, q_last, 1) != 0)
724 		goto on_error;
725 
726 	res_id = radius_get_id(q->res);
727 	res_code = radius_get_code(q->res);
728 
729 	/* Reset response/message authenticator */
730 	if (radius_has_attr(q->res, RADIUS_TYPE_MESSAGE_AUTHENTICATOR))
731 		radius_del_attr_all(q->res, RADIUS_TYPE_MESSAGE_AUTHENTICATOR);
732 	radius_put_message_authenticator(q->res, q->client->secret);
733 	radius_set_response_authenticator(q->res, q->client->secret);
734 
735 	log_info("Sending %s(code=%d) to %s id=%u q=%u",
736 	    radius_code_string(res_code), res_code,
737 	    addrport_tostring((struct sockaddr *)&q->clientaddr,
738 		    q->clientaddrlen, buf, sizeof(buf)), res_id, q->id);
739 
740 	if ((sz = sendto(q->listen->sock, radius_get_data(q->res),
741 	    radius_get_length(q->res), 0,
742 	    (struct sockaddr *)&q->clientaddr, q->clientaddrlen)) <= 0)
743 		log_warn("Sending a RADIUS response failed");
744 on_error:
745 	radiusd_access_request_aborted(q);
746 }
747 
748 static void
749 raidus_query_accounting_request(struct radiusd_accounting *accounting,
750     struct radius_query *q)
751 {
752 	int		 req_code;
753 	uint32_t	 acct_status;
754 	char		 buf0[NI_MAXHOST + NI_MAXSERV + 30];
755 
756 	if (accounting != NULL) {
757 		/* handle by the module */
758 		if (MODULE_DO_ACCTREQ(accounting->acct->module))
759 			radiusd_module_account_request(accounting->acct->module,
760 			    q);
761 		return;
762 	}
763 	req_code = radius_get_code(q->req);
764 	if (radius_get_uint32_attr(q->req, RADIUS_TYPE_ACCT_STATUS_TYPE,
765 	    &acct_status) != 0)
766 		acct_status = 0;
767 	log_info("Received %s(code=%d) type=%s(%lu) from %s id=%d username=%s "
768 	    "q=%u", radius_code_string(req_code), req_code,
769 	    radius_acct_status_type_string(acct_status), (unsigned long)
770 	    acct_status, addrport_tostring((struct sockaddr *)&q->clientaddr,
771 	    q->clientaddrlen, buf0, sizeof(buf0)), q->req_id, q->username,
772 	    q->id);
773 }
774 
775 static void
776 radius_query_accounting_response(struct radius_query *q)
777 {
778 	int		 sz, res_id, res_code;
779 	char		 buf[NI_MAXHOST + NI_MAXSERV + 30];
780 
781 	radius_set_response_authenticator(q->res, q->client->secret);
782 	res_id = radius_get_id(q->res);
783 	res_code = radius_get_code(q->res);
784 
785 	log_info("Sending %s(code=%d) to %s id=%u q=%u",
786 	    radius_code_string(res_code), res_code,
787 	    addrport_tostring((struct sockaddr *)&q->clientaddr,
788 		    q->clientaddrlen, buf, sizeof(buf)), res_id, q->id);
789 
790 	if ((sz = sendto(q->listen->sock, radius_get_data(q->res),
791 	    radius_get_length(q->res), 0,
792 	    (struct sockaddr *)&q->clientaddr, q->clientaddrlen)) <= 0)
793 		log_warn("Sending a RADIUS response failed");
794 }
795 
796 static const char *
797 radius_query_client_secret(struct radius_query *q)
798 {
799 	struct radius_query	*q0;
800 	const char		*client_secret = NULL;
801 
802 	for (q0 = q; q0 != NULL && client_secret == NULL; q0 = q0->prev) {
803 		if (q0->client != NULL)
804 			client_secret = q0->client->secret;
805 	}
806 	RADIUSD_ASSERT(client_secret != NULL);
807 
808 	return (client_secret);
809 }
810 /***********************************************************************
811  * Callback functions from the modules
812  ***********************************************************************/
813 void
814 radiusd_access_request_answer(struct radius_query *q)
815 {
816 	radius_set_request_packet(q->res, q->req);
817 	RADIUSD_ASSERT(q->deco == NULL);
818 
819 	radius_query_access_response(q);
820 }
821 
822 void
823 radiusd_access_request_next(struct radius_query *q, RADIUS_PACKET *pkt)
824 {
825 	struct radius_query		*q_next = NULL;
826 	static char			 username[256];
827 	struct radiusd_authentication	*authen;
828 	int				 i;
829 
830 	RADIUSD_ASSERT(q->deco == NULL);
831 
832 	if (!q->authen->isfilter) {
833 		log_warnx("q=%u `%s' requested next authentication, but it's "
834 		    "not authentication-filter", q->id,
835 		    q->authen->auth->module->name);
836 		goto on_error;
837 	}
838 	if (radius_get_string_attr(pkt, RADIUS_TYPE_USER_NAME, username,
839 	    sizeof(username)) != 0)
840 		username[0] = '\0';
841 
842 	for (authen = TAILQ_NEXT(q->authen, next); authen != NULL;
843 	    authen = TAILQ_NEXT(authen, next)) {
844 		for (i = 0; authen->username[i] != NULL; i++) {
845 			if (fnmatch(authen->username[i], username, 0)
846 			    == 0)
847 				goto found;
848 		}
849 	}
850  found:
851 	if (authen == NULL) {	/* no more authentication */
852 		log_warnx("q=%u module `%s' requested next authentication "
853 		    "no more `authenticate' matches", q->id,
854 		    q->authen->auth->module->name);
855 		goto on_error;
856 	}
857 
858 	if ((q_next = calloc(1, sizeof(struct radius_query))) == NULL) {
859 		log_warn("%s: q=%u calloc: %m", __func__, q->id);
860 		goto on_error;
861 	}
862 	q_next->id = ++radius_query_id_seq;
863 	q_next->radiusd = q->radiusd;
864 	q_next->req_id = q->req_id;
865 	q_next->req = pkt;
866 	radius_get_authenticator(pkt, q_next->req_auth);
867 	q_next->authen = authen;
868 	q_next->prev = q;
869 	q->hasnext = true;
870 	strlcpy(q_next->username, username, sizeof(q_next->username));
871 	TAILQ_INSERT_TAIL(&q->radiusd->query, q_next, next);
872 
873 	raidus_query_access_request(q_next);
874 	return;
875  on_error:
876 	RADIUSD_ASSERT(q_next == NULL);
877 	radius_delete_packet(pkt);
878 	radiusd_access_request_aborted(q);
879 }
880 
881 void
882 radiusd_access_request_aborted(struct radius_query *q)
883 {
884 	if (q->hasnext)	/* don't abort if filtering */
885 		return;
886 	if (q->prev != NULL) {
887 		q->prev->hasnext = false;
888 		radiusd_access_request_aborted(q->prev);
889 	}
890 	if (q->req != NULL)
891 		radius_delete_packet(q->req);
892 	if (q->res != NULL)
893 		radius_delete_packet(q->res);
894 	TAILQ_REMOVE(&q->radiusd->query, q, next);
895 	free(q);
896 }
897 
898 /***********************************************************************
899  * Signal handlers
900  ***********************************************************************/
901 static void
902 radiusd_on_sigterm(int fd, short evmask, void *ctx)
903 {
904 	log_info("Received SIGTERM");
905 	event_loopbreak();
906 }
907 
908 static void
909 radiusd_on_sigint(int fd, short evmask, void *ctx)
910 {
911 	log_info("Received SIGINT");
912 	event_loopbreak();
913 }
914 
915 static void
916 radiusd_on_sighup(int fd, short evmask, void *ctx)
917 {
918 	log_info("Received SIGHUP");
919 }
920 
921 static void
922 radiusd_on_sigchld(int fd, short evmask, void *ctx)
923 {
924 	struct radiusd		*radiusd = ctx;
925 	struct radiusd_module	*module;
926 	pid_t			 pid;
927 	int			 status, ndeath = 0;
928 
929 	log_debug("Received SIGCHLD");
930 	while ((pid = wait3(&status, WNOHANG, NULL)) != 0) {
931 		if (pid == -1)
932 			break;
933 		TAILQ_FOREACH(module, &radiusd->module, next) {
934 			if (module->pid == pid) {
935 				if (WIFEXITED(status))
936 					log_warnx("module `%s'(pid=%d) exited "
937 					    "with status %d", module->name,
938 					    (int)pid, WEXITSTATUS(status));
939 				else
940 					log_warnx("module `%s'(pid=%d) exited "
941 					    "by signal %d", module->name,
942 					    (int)pid, WTERMSIG(status));
943 				ndeath++;
944 				break;
945 			}
946 		}
947 		if (!module) {
948 			if (WIFEXITED(status))
949 				log_warnx("unknown child process pid=%d exited "
950 				    "with status %d", (int)pid,
951 				     WEXITSTATUS(status));
952 			else
953 				log_warnx("unknown child process pid=%d exited "
954 				    "by signal %d", (int)pid,
955 				    WTERMSIG(status));
956 		}
957 	}
958 	if (ndeath > 0) {
959 		radiusd->error++;
960 		event_loopbreak();
961 	}
962 }
963 
964 static const char *
965 radius_code_string(int code)
966 {
967 	int			i;
968 	struct _codestrings {
969 		int		 code;
970 		const char	*string;
971 	} codestrings[] = {
972 	    { RADIUS_CODE_ACCESS_REQUEST,	"Access-Request" },
973 	    { RADIUS_CODE_ACCESS_ACCEPT,	"Access-Accept" },
974 	    { RADIUS_CODE_ACCESS_REJECT,	"Access-Reject" },
975 	    { RADIUS_CODE_ACCOUNTING_REQUEST,	"Accounting-Request" },
976 	    { RADIUS_CODE_ACCOUNTING_RESPONSE,	"Accounting-Response" },
977 	    { RADIUS_CODE_ACCESS_CHALLENGE,	"Access-Challenge" },
978 	    { RADIUS_CODE_STATUS_SERVER,	"Status-Server" },
979 	    { RADIUS_CODE_STATUS_CLIENT,	"Status-Client" },
980 	    { -1,				NULL }
981 	};
982 
983 	for (i = 0; codestrings[i].code != -1; i++)
984 		if (codestrings[i].code == code)
985 			return (codestrings[i].string);
986 
987 	return ("Unknown");
988 }
989 
990 static const char *
991 radius_acct_status_type_string(uint32_t type)
992 {
993 	int			i;
994 	struct _typestrings {
995 		uint32_t	 type;
996 		const char	*string;
997 	} typestrings[] = {
998 	    { RADIUS_ACCT_STATUS_TYPE_START,		"Start" },
999 	    { RADIUS_ACCT_STATUS_TYPE_STOP,		"Stop" },
1000 	    { RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE,	"Interim-Update" },
1001 	    { RADIUS_ACCT_STATUS_TYPE_ACCT_ON,		"Accounting-On" },
1002 	    { RADIUS_ACCT_STATUS_TYPE_ACCT_OFF,		"Accounting-Off" },
1003 	    { -1,					NULL }
1004 	};
1005 
1006 	for (i = 0; typestrings[i].string != NULL; i++)
1007 		if (typestrings[i].type == type)
1008 			return (typestrings[i].string);
1009 
1010 	return ("Unknown");
1011 }
1012 
1013 void
1014 radiusd_conf_init(struct radiusd *conf)
1015 {
1016 
1017 	TAILQ_INIT(&conf->listen);
1018 	TAILQ_INIT(&conf->module);
1019 	TAILQ_INIT(&conf->authen);
1020 	TAILQ_INIT(&conf->account);
1021 	TAILQ_INIT(&conf->client);
1022 
1023 	return;
1024 }
1025 
1026 /*
1027  * Fix some attributes which depend the secret value.
1028  */
1029 static int
1030 radiusd_access_response_fixup(struct radius_query *q, struct radius_query *q0,
1031     bool islast)
1032 {
1033 	int			 res_id;
1034 	size_t			 attrlen;
1035 	u_char			 authen_req_auth[16], attrbuf[256];
1036 	const char		*client_req_auth;
1037 	const char		*authen_secret, *client_secret;
1038 
1039 	authen_secret = q0->authen->auth->module->secret;
1040 	client_secret = (islast)? q->client->secret :
1041 	    q->authen->auth->module->secret;
1042 
1043 	radius_get_authenticator(q0->req, authen_req_auth);
1044 	client_req_auth = q->req_auth;
1045 
1046 	if (client_secret == NULL && authen_secret == NULL)
1047 		return (0);
1048 	if (!(authen_secret != NULL && client_secret != NULL &&
1049 	    strcmp(authen_secret, client_secret) == 0 &&
1050 	    timingsafe_bcmp(authen_req_auth, client_req_auth, 16) == 0)) {
1051 		/* RFC 2865 Tunnel-Password */
1052 		attrlen = sizeof(attrbuf);
1053 		if (radius_get_raw_attr(q0->res, RADIUS_TYPE_TUNNEL_PASSWORD,
1054 		    attrbuf, &attrlen) == 0) {
1055 			if (authen_secret != NULL)
1056 				radius_attr_unhide(authen_secret,
1057 				    authen_req_auth, attrbuf, attrbuf + 3,
1058 				    attrlen - 3);
1059 			if (client_secret != NULL)
1060 				radius_attr_hide(client_secret, client_req_auth,
1061 				    attrbuf, attrbuf + 3, attrlen - 3);
1062 			radius_del_attr_all(q0->res,
1063 			    RADIUS_TYPE_TUNNEL_PASSWORD);
1064 			radius_put_raw_attr(q0->res,
1065 			    RADIUS_TYPE_TUNNEL_PASSWORD, attrbuf, attrlen);
1066 		}
1067 
1068 		/* RFC 2548 Microsoft MPPE-{Send,Recv}-Key */
1069 		attrlen = sizeof(attrbuf);
1070 		if (radius_get_vs_raw_attr(q0->res, RADIUS_VENDOR_MICROSOFT,
1071 		    RADIUS_VTYPE_MPPE_SEND_KEY, attrbuf, &attrlen) == 0) {
1072 			if (authen_secret != NULL)
1073 				radius_attr_unhide(authen_secret,
1074 				    authen_req_auth, attrbuf, attrbuf + 2,
1075 				    attrlen - 2);
1076 			if (client_secret != NULL)
1077 				radius_attr_hide(client_secret, client_req_auth,
1078 				    attrbuf, attrbuf + 2, attrlen - 2);
1079 			radius_del_vs_attr_all(q0->res, RADIUS_VENDOR_MICROSOFT,
1080 			    RADIUS_VTYPE_MPPE_SEND_KEY);
1081 			radius_put_vs_raw_attr(q0->res, RADIUS_VENDOR_MICROSOFT,
1082 			    RADIUS_VTYPE_MPPE_SEND_KEY, attrbuf, attrlen);
1083 		}
1084 		attrlen = sizeof(attrbuf);
1085 		if (radius_get_vs_raw_attr(q0->res, RADIUS_VENDOR_MICROSOFT,
1086 		    RADIUS_VTYPE_MPPE_RECV_KEY, attrbuf, &attrlen) == 0) {
1087 			if (authen_secret != NULL)
1088 				radius_attr_unhide(authen_secret,
1089 				    authen_req_auth, attrbuf, attrbuf + 2,
1090 				    attrlen - 2);
1091 			if (client_secret != NULL)
1092 				radius_attr_hide(client_secret, client_req_auth,
1093 				    attrbuf, attrbuf + 2, attrlen - 2);
1094 
1095 			radius_del_vs_attr_all(q0->res, RADIUS_VENDOR_MICROSOFT,
1096 			    RADIUS_VTYPE_MPPE_RECV_KEY);
1097 			radius_put_vs_raw_attr(q0->res, RADIUS_VENDOR_MICROSOFT,
1098 			    RADIUS_VTYPE_MPPE_RECV_KEY, attrbuf, attrlen);
1099 		}
1100 	}
1101 	res_id = radius_get_id(q0->res);
1102 	if (res_id != q->req_id) {
1103 		/* authentication server change the id */
1104 		radius_set_id(q0->res, q->req_id);
1105 	}
1106 
1107 	return (0);
1108 }
1109 
1110 static struct radius_query *
1111 radiusd_find_query(struct radiusd *radiusd, u_int q_id)
1112 {
1113 	struct radius_query	*q;
1114 
1115 	TAILQ_FOREACH(q, &radiusd->query, next) {
1116 		if (q->id == q_id)
1117 			return (q);
1118 	}
1119 	return (NULL);
1120 }
1121 
1122 int
1123 radiusd_imsg_compose_module(struct radiusd *radiusd, const char *module_name,
1124     uint32_t type, uint32_t id, pid_t pid, int fd, void *data, size_t datalen)
1125 {
1126 	struct radiusd_module	*module;
1127 
1128 	TAILQ_FOREACH(module, &radiusd_s->module, next) {
1129 		if (strcmp(module->name, module_name) == 0)
1130 			break;
1131 	}
1132 	if (module == NULL ||
1133 	    (module->capabilities & RADIUSD_MODULE_CAP_CONTROL) == 0 ||
1134 	    module->fd < 0)
1135 		return (-1);
1136 
1137 	if (imsg_compose(&module->ibuf, type, id, pid, fd, data,
1138 	    datalen) == -1)
1139 		return (-1);
1140 	radiusd_module_reset_ev_handler(module);
1141 
1142 	return (0);
1143 }
1144 
1145 /***********************************************************************
1146  * radiusd module handling
1147  ***********************************************************************/
1148 struct radiusd_module *
1149 radiusd_module_load(struct radiusd *radiusd, const char *path, const char *name)
1150 {
1151 	struct radiusd_module		*module = NULL;
1152 	pid_t				 pid;
1153 	int				 ival, pairsock[] = { -1, -1 };
1154 	const char			*av[3];
1155 	ssize_t				 n;
1156 	struct imsg			 imsg;
1157 
1158 	module = calloc(1, sizeof(struct radiusd_module));
1159 	if (module == NULL)
1160 		fatal("Out of memory");
1161 	module->radiusd = radiusd;
1162 
1163 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pairsock) == -1) {
1164 		log_warn("Could not load module `%s'(%s): pipe()", name, path);
1165 		goto on_error;
1166 	}
1167 
1168 	pid = fork();
1169 	if (pid == -1) {
1170 		log_warn("Could not load module `%s'(%s): fork()", name, path);
1171 		goto on_error;
1172 	}
1173 	if (pid == 0) {
1174 		setsid();
1175 		close(pairsock[0]);
1176 		av[0] = path;
1177 		av[1] = name;
1178 		av[2] = NULL;
1179 		dup2(pairsock[1], STDIN_FILENO);
1180 		dup2(pairsock[1], STDOUT_FILENO);
1181 		close(pairsock[1]);
1182 		closefrom(STDERR_FILENO + 1);
1183 		execv(path, (char * const *)av);
1184 		log_warn("Failed to execute %s", path);
1185 		_exit(EXIT_FAILURE);
1186 	}
1187 	close(pairsock[1]);
1188 
1189 	module->fd = pairsock[0];
1190 	if ((ival = fcntl(module->fd, F_GETFL)) == -1) {
1191 		log_warn("Could not load module `%s': fcntl(F_GETFL)",
1192 		    name);
1193 		goto on_error;
1194 	}
1195 	if (fcntl(module->fd, F_SETFL, ival | O_NONBLOCK) == -1) {
1196 		log_warn(
1197 		    "Could not load module `%s': fcntl(F_SETFL,O_NONBLOCK)",
1198 		    name);
1199 		goto on_error;
1200 	}
1201 	strlcpy(module->name, name, sizeof(module->name));
1202 	module->pid = pid;
1203 	if (imsgbuf_init(&module->ibuf, module->fd) == -1) {
1204 		log_warn("Could not load module `%s': imsgbuf_init", name);
1205 		goto on_error;
1206 	}
1207 
1208 	if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0 ||
1209 	    (n = imsg_get(&module->ibuf, &imsg)) <= 0) {
1210 		log_warnx("Could not load module `%s': module didn't "
1211 		    "respond", name);
1212 		goto on_error;
1213 	}
1214 	if (imsg.hdr.type != IMSG_RADIUSD_MODULE_LOAD) {
1215 		imsg_free(&imsg);
1216 		log_warnx("Could not load module `%s': unknown imsg type=%d",
1217 		    name, imsg.hdr.type);
1218 		goto on_error;
1219 	}
1220 
1221 	module->capabilities =
1222 	    ((struct radiusd_module_load_arg *)imsg.data)->cap;
1223 
1224 	log_debug("Loaded module `%s' successfully.  pid=%d", module->name,
1225 	    module->pid);
1226 	imsg_free(&imsg);
1227 
1228 	return (module);
1229 
1230 on_error:
1231 	free(module);
1232 	if (pairsock[0] >= 0)
1233 		close(pairsock[0]);
1234 	if (pairsock[1] >= 0)
1235 		close(pairsock[1]);
1236 
1237 	return (NULL);
1238 }
1239 
1240 void
1241 radiusd_module_start(struct radiusd_module *module)
1242 {
1243 	int		 datalen;
1244 	struct imsg	 imsg;
1245 	struct timeval	 tv = { 0, 0 };
1246 
1247 	RADIUSD_ASSERT(module->fd >= 0);
1248 	imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_START, 0, 0, -1,
1249 	    NULL, 0);
1250 	imsg_sync_flush(&module->ibuf, MODULE_IO_TIMEOUT);
1251 	if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0 ||
1252 	    imsg_get(&module->ibuf, &imsg) <= 0) {
1253 		log_warnx("Module `%s' could not start: no response",
1254 		    module->name);
1255 		goto on_fail;
1256 	}
1257 
1258 	datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1259 	if (imsg.hdr.type != IMSG_OK) {
1260 		if (imsg.hdr.type == IMSG_NG) {
1261 			if (datalen > 0)
1262 				log_warnx("Module `%s' could not start: %s",
1263 				    module->name, (char *)imsg.data);
1264 			else
1265 				log_warnx("Module `%s' could not start",
1266 				    module->name);
1267 		} else
1268 			log_warnx("Module `%s' could not started: module "
1269 			    "returned unknown message type %d", module->name,
1270 			    imsg.hdr.type);
1271 		goto on_fail;
1272 	}
1273 
1274 	event_set(&module->ev, module->fd, EV_READ, radiusd_module_on_imsg_io,
1275 	    module);
1276 	event_add(&module->ev, &tv);
1277 	log_debug("Module `%s' started successfully", module->name);
1278 
1279 	return;
1280 on_fail:
1281 	radiusd_module_close(module);
1282 	return;
1283 }
1284 
1285 void
1286 radiusd_module_stop(struct radiusd_module *module)
1287 {
1288 	module->stopped = true;
1289 
1290 	if (module->secret != NULL) {
1291 		freezero(module->secret, strlen(module->secret));
1292 		module->secret = NULL;
1293 	}
1294 
1295 	if (module->fd >= 0) {
1296 		imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_STOP, 0, 0, -1,
1297 		    NULL, 0);
1298 		radiusd_module_reset_ev_handler(module);
1299 	}
1300 }
1301 
1302 static void
1303 radiusd_module_close(struct radiusd_module *module)
1304 {
1305 	if (module->fd >= 0) {
1306 		event_del(&module->ev);
1307 		imsgbuf_clear(&module->ibuf);
1308 		close(module->fd);
1309 		module->fd = -1;
1310 	}
1311 }
1312 
1313 void
1314 radiusd_module_unload(struct radiusd_module *module)
1315 {
1316 	free(module->radpkt);
1317 	radiusd_module_close(module);
1318 	free(module);
1319 }
1320 
1321 static void
1322 radiusd_module_on_imsg_io(int fd, short evmask, void *ctx)
1323 {
1324 	struct radiusd_module	*module = ctx;
1325 
1326 	if (evmask & EV_WRITE) {
1327 		module->writeready = true;
1328 		if (imsgbuf_write(&module->ibuf) == -1) {
1329 			log_warn("Failed to write to module `%s': "
1330 			    "imsgbuf_write()", module->name);
1331 			goto on_error;
1332 		}
1333 		module->writeready = false;
1334 	}
1335 
1336 	if (evmask & EV_READ) {
1337 		if (radiusd_module_imsg_read(module) == -1)
1338 			goto on_error;
1339 	}
1340 
1341 	radiusd_module_reset_ev_handler(module);
1342 
1343 	return;
1344 on_error:
1345 	radiusd_module_close(module);
1346 }
1347 
1348 static void
1349 radiusd_module_reset_ev_handler(struct radiusd_module *module)
1350 {
1351 	short		 evmask;
1352 	struct timeval	*tvp = NULL, tv = { 0, 0 };
1353 
1354 	RADIUSD_ASSERT(module->fd >= 0);
1355 	event_del(&module->ev);
1356 
1357 	evmask = EV_READ;
1358 	if (imsgbuf_queuelen(&module->ibuf) > 0) {
1359 		if (!module->writeready)
1360 			evmask |= EV_WRITE;
1361 		else
1362 			tvp = &tv;	/* fire immediately */
1363 	}
1364 
1365 	/* module stopped and no event handler is set */
1366 	if (evmask & EV_WRITE && tvp == NULL && module->stopped) {
1367 		/* stop requested and no more to write */
1368 		radiusd_module_close(module);
1369 		return;
1370 	}
1371 
1372 	event_set(&module->ev, module->fd, evmask, radiusd_module_on_imsg_io,
1373 	    module);
1374 	if (event_add(&module->ev, tvp) == -1) {
1375 		log_warn("Could not set event handlers for module `%s': "
1376 		    "event_add()", module->name);
1377 		radiusd_module_close(module);
1378 	}
1379 }
1380 
1381 static int
1382 radiusd_module_imsg_read(struct radiusd_module *module)
1383 {
1384 	int		 n;
1385 	struct imsg	 imsg;
1386 
1387 	if ((n = imsgbuf_read(&module->ibuf)) != 1) {
1388 		if (n == -1)
1389 			log_warn("Receiving a message from module `%s' "
1390 			    "failed: imsgbuf_read", module->name);
1391 		/* else closed */
1392 		radiusd_module_close(module);
1393 		return (-1);
1394 	}
1395 	for (;;) {
1396 		if ((n = imsg_get(&module->ibuf, &imsg)) == -1) {
1397 			log_warn("Receiving a message from module `%s' failed: "
1398 			    "imsg_get", module->name);
1399 			return (-1);
1400 		}
1401 		if (n == 0)
1402 			return (0);
1403 		radiusd_module_imsg(module, &imsg);
1404 		imsg_free(&imsg);
1405 	}
1406 
1407 	return (0);
1408 }
1409 
1410 static void
1411 radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
1412 {
1413 	int			 datalen;
1414 	struct radius_query	*q;
1415 	u_int			 q_id;
1416 
1417 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
1418 	switch (imsg->hdr.type) {
1419 	case IMSG_RADIUSD_MODULE_NOTIFY_SECRET:
1420 		if (datalen > 0) {
1421 			module->secret = strdup(imsg->data);
1422 			if (module->secret == NULL)
1423 				log_warn("Could not handle NOTIFY_SECRET "
1424 				    "from `%s'", module->name);
1425 		}
1426 		break;
1427 	case IMSG_RADIUSD_MODULE_USERPASS_OK:
1428 	case IMSG_RADIUSD_MODULE_USERPASS_FAIL:
1429 	    {
1430 		char			*msg = NULL;
1431 		const char		*msgtypestr;
1432 
1433 		msgtypestr = (imsg->hdr.type == IMSG_RADIUSD_MODULE_USERPASS_OK)
1434 		    ? "USERPASS_OK" : "USERPASS_NG";
1435 
1436 		q_id = *(u_int *)imsg->data;
1437 		if (datalen > (ssize_t)sizeof(u_int))
1438 			msg = (char *)(((u_int *)imsg->data) + 1);
1439 
1440 		q = radiusd_find_query(module->radiusd, q_id);
1441 		if (q == NULL) {
1442 			log_warnx("Received %s from `%s', but query id=%u "
1443 			    "unknown", msgtypestr, module->name, q_id);
1444 			break;
1445 		}
1446 
1447 		if ((q->res = radius_new_response_packet(
1448 		    (imsg->hdr.type == IMSG_RADIUSD_MODULE_USERPASS_OK)
1449 		    ? RADIUS_CODE_ACCESS_ACCEPT : RADIUS_CODE_ACCESS_REJECT,
1450 		    q->req)) == NULL) {
1451 			log_warn("radius_new_response_packet() failed");
1452 			radiusd_access_request_aborted(q);
1453 		} else {
1454 			if (msg)
1455 				radius_put_string_attr(q->res,
1456 				    RADIUS_TYPE_REPLY_MESSAGE, msg);
1457 			radius_set_response_authenticator(q->res,
1458 			    radius_query_client_secret(q));
1459 			radiusd_access_request_answer(q);
1460 		}
1461 		break;
1462 	    }
1463 	case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1464 	case IMSG_RADIUSD_MODULE_ACCSREQ_NEXT:
1465 	case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1466 	case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1467 	    {
1468 		static struct radiusd_module_radpkt_arg *ans;
1469 		const char *typestr = "unknown";
1470 
1471 		switch (imsg->hdr.type) {
1472 		case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1473 			typestr = "ACCSREQ_ANSWER";
1474 			break;
1475 		case IMSG_RADIUSD_MODULE_ACCSREQ_NEXT:
1476 			typestr = "ACCSREQ_NEXT";
1477 			break;
1478 		case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1479 			typestr = "REQDECO_DONE";
1480 			break;
1481 		case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1482 			typestr = "RESDECO_DONE";
1483 			break;
1484 		}
1485 
1486 		if (datalen <
1487 		    (ssize_t)sizeof(struct radiusd_module_radpkt_arg)) {
1488 			log_warnx("Received %s message, but length is wrong",
1489 			    typestr);
1490 			break;
1491 		}
1492 		q_id = ((struct radiusd_module_radpkt_arg *)imsg->data)->q_id;
1493 		q = radiusd_find_query(module->radiusd, q_id);
1494 		if (q == NULL) {
1495 			log_warnx("Received %s from %s, but query id=%u "
1496 			    "unknown", typestr, module->name, q_id);
1497 			break;
1498 		}
1499 		if ((ans = radiusd_module_recv_radpkt(module, imsg,
1500 		    imsg->hdr.type, typestr)) != NULL) {
1501 			RADIUS_PACKET *radpkt = NULL;
1502 
1503 			if (module->radpktoff > 0 &&
1504 			    (radpkt = radius_convert_packet(
1505 			    module->radpkt, module->radpktoff)) == NULL) {
1506 				log_warn("q=%u radius_convert_packet() failed",
1507 				    q->id);
1508 				radiusd_access_request_aborted(q);
1509 				break;
1510 			}
1511 			module->radpktoff = 0;
1512 			switch (imsg->hdr.type) {
1513 			case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1514 				if (q->deco == NULL || q->deco->type !=
1515 				    IMSG_RADIUSD_MODULE_REQDECO) {
1516 					log_warnx("q=%u received %s but not "
1517 					    "requested", q->id, typestr);
1518 					if (radpkt != NULL)
1519 						radius_delete_packet(radpkt);
1520 					break;
1521 				}
1522 				if (radpkt != NULL) {
1523 					radius_delete_packet(q->req);
1524 					q->req = radpkt;
1525 				}
1526 				raidus_query_access_request(q);
1527 				break;
1528 			case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1529 				if (radpkt == NULL) {
1530 					log_warnx("q=%u wrong pkt from module",
1531 					    q->id);
1532 					radiusd_access_request_aborted(q);
1533 					break;
1534 				}
1535 				q->res = radpkt;
1536 				radiusd_access_request_answer(q);
1537 				break;
1538 			case IMSG_RADIUSD_MODULE_ACCSREQ_NEXT:
1539 				if (radpkt == NULL) {
1540 					log_warnx("q=%u wrong pkt from module",
1541 					    q->id);
1542 					radiusd_access_request_aborted(q);
1543 					break;
1544 				}
1545 				radiusd_access_request_next(q, radpkt);
1546 				break;
1547 			case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1548 				if (q->deco == NULL || q->deco->type !=
1549 				    IMSG_RADIUSD_MODULE_RESDECO) {
1550 					log_warnx("q=%u received %s but not "
1551 					    "requested", q->id, typestr);
1552 					if (radpkt != NULL)
1553 						radius_delete_packet(radpkt);
1554 					break;
1555 				}
1556 				if (radpkt != NULL) {
1557 					radius_delete_packet(q->res);
1558 					radius_set_request_packet(radpkt,
1559 					    q->req);
1560 					q->res = radpkt;
1561 				}
1562 				radius_query_access_response(q);
1563 				break;
1564 			}
1565 		}
1566 		break;
1567 	    }
1568 	case IMSG_RADIUSD_MODULE_ACCSREQ_ABORTED:
1569 	    {
1570 		if (datalen < (ssize_t)sizeof(u_int)) {
1571 			log_warnx("Received ACCSREQ_ABORTED message, but "
1572 			    "length is wrong");
1573 			break;
1574 		}
1575 		q_id = *((u_int *)imsg->data);
1576 		q = radiusd_find_query(module->radiusd, q_id);
1577 		if (q == NULL) {
1578 			log_warnx("Received ACCSREQ_ABORT from %s, but query "
1579 			    "id=%u unknown", module->name, q_id);
1580 			break;
1581 		}
1582 		radiusd_access_request_aborted(q);
1583 		break;
1584 	    }
1585 	case IMSG_RADIUSD_MODULE_CTRL_BIND:
1586 		control_conn_bind(imsg->hdr.peerid, module->name);
1587 		break;
1588 	default:
1589 		if (imsg->hdr.peerid != 0)
1590 			control_imsg_relay(imsg);
1591 		else
1592 			RADIUSD_DBG(("Unhandled imsg type=%d from %s",
1593 			    imsg->hdr.type, module->name));
1594 	}
1595 }
1596 
1597 static struct radiusd_module_radpkt_arg *
1598 radiusd_module_recv_radpkt(struct radiusd_module *module, struct imsg *imsg,
1599     uint32_t imsg_type, const char *type_str)
1600 {
1601 	struct radiusd_module_radpkt_arg	*ans;
1602 	int					 datalen, chunklen;
1603 
1604 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
1605 	ans = (struct radiusd_module_radpkt_arg *)imsg->data;
1606 	if (module->radpktsiz < ans->pktlen) {
1607 		u_char *nradpkt;
1608 		if ((nradpkt = realloc(module->radpkt, ans->pktlen)) == NULL) {
1609 			log_warn("Could not handle received %s message from "
1610 			    "`%s'", type_str, module->name);
1611 			goto on_fail;
1612 		}
1613 		module->radpkt = nradpkt;
1614 		module->radpktsiz = ans->pktlen;
1615 	}
1616 	chunklen = datalen - sizeof(struct radiusd_module_radpkt_arg);
1617 	if (chunklen > module->radpktsiz - module->radpktoff) {
1618 		log_warnx("Could not handle received %s message from `%s': "
1619 		    "received length is too big", type_str, module->name);
1620 		goto on_fail;
1621 	}
1622 	if (chunklen > 0) {
1623 		memcpy(module->radpkt + module->radpktoff,
1624 		    (caddr_t)(ans + 1), chunklen);
1625 		module->radpktoff += chunklen;
1626 	}
1627 	if (!ans->final)
1628 		return (NULL);	/* again */
1629 	if (module->radpktoff != ans->pktlen) {
1630 		log_warnx("Could not handle received %s message from `%s': "
1631 		    "length is mismatch", type_str, module->name);
1632 		goto on_fail;
1633 	}
1634 
1635 	return (ans);
1636 on_fail:
1637 	module->radpktoff = 0;
1638 	return (NULL);
1639 }
1640 
1641 int
1642 radiusd_module_set(struct radiusd_module *module, const char *name,
1643     int argc, char * const * argv)
1644 {
1645 	struct radiusd_module_set_arg	 arg;
1646 	struct radiusd_module_object	*val;
1647 	int				 i, niov = 0;
1648 	u_char				*buf = NULL, *buf0;
1649 	ssize_t				 n;
1650 	size_t				 bufsiz = 0, bufoff = 0, bufsiz0;
1651 	size_t				 vallen, valsiz;
1652 	struct iovec			 iov[2];
1653 	struct imsg			 imsg;
1654 
1655 	memset(&arg, 0, sizeof(arg));
1656 	arg.nparamval = argc;
1657 	strlcpy(arg.paramname, name, sizeof(arg.paramname));
1658 
1659 	iov[niov].iov_base = &arg;
1660 	iov[niov].iov_len = sizeof(struct radiusd_module_set_arg);
1661 	niov++;
1662 
1663 	for (i = 0; i < argc; i++) {
1664 		vallen = strlen(argv[i]) + 1;
1665 		valsiz = sizeof(struct radiusd_module_object) + vallen;
1666 		if (bufsiz < bufoff + valsiz) {
1667 			bufsiz0 = bufoff + valsiz + 128;
1668 			if ((buf0 = realloc(buf, bufsiz0)) == NULL) {
1669 				log_warn("Failed to set config parameter to "
1670 				    "module `%s': realloc", module->name);
1671 				goto on_error;
1672 			}
1673 			buf = buf0;
1674 			bufsiz = bufsiz0;
1675 			memset(buf + bufoff, 0, bufsiz - bufoff);
1676 		}
1677 		val = (struct radiusd_module_object *)(buf + bufoff);
1678 		val->size = valsiz;
1679 		memcpy(val + 1, argv[i], vallen);
1680 
1681 		bufoff += valsiz;
1682 	}
1683 	iov[niov].iov_base = buf;
1684 	iov[niov].iov_len = bufoff;
1685 	niov++;
1686 
1687 	if (imsg_composev(&module->ibuf, IMSG_RADIUSD_MODULE_SET_CONFIG, 0, 0,
1688 	    -1, iov, niov) == -1) {
1689 		log_warn("Failed to set config parameter to module `%s': "
1690 		    "imsg_composev", module->name);
1691 		goto on_error;
1692 	}
1693 	if (imsg_sync_flush(&module->ibuf, MODULE_IO_TIMEOUT) == -1) {
1694 		log_warn("Failed to set config parameter to module `%s': "
1695 		    "imsg_flush_timeout", module->name);
1696 		goto on_error;
1697 	}
1698 	for (;;) {
1699 		if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0) {
1700 			log_warn("Failed to get reply from module `%s': "
1701 			    "imsg_sync_read", module->name);
1702 			goto on_error;
1703 		}
1704 		if ((n = imsg_get(&module->ibuf, &imsg)) > 0)
1705 			break;
1706 		if (n < 0) {
1707 			log_warn("Failed to get reply from module `%s': "
1708 			    "imsg_get", module->name);
1709 			goto on_error;
1710 		}
1711 	}
1712 	if (imsg.hdr.type == IMSG_NG) {
1713 		log_warnx("Could not set `%s' for module `%s': %s", name,
1714 		    module->name, (char *)imsg.data);
1715 		goto on_error;
1716 	} else if (imsg.hdr.type != IMSG_OK) {
1717 		imsg_free(&imsg);
1718 		log_warnx("Failed to get reply from module `%s': "
1719 		    "unknown imsg type=%d", module->name, imsg.hdr.type);
1720 		goto on_error;
1721 	}
1722 	imsg_free(&imsg);
1723 
1724 	free(buf);
1725 	return (0);
1726 
1727 on_error:
1728 	free(buf);
1729 	return (-1);
1730 }
1731 
1732 static void
1733 radiusd_module_userpass(struct radiusd_module *module, struct radius_query *q)
1734 {
1735 	struct radiusd_module_userpass_arg userpass;
1736 
1737 	memset(&userpass, 0, sizeof(userpass));
1738 	userpass.q_id = q->id;
1739 
1740 	if (radius_get_user_password_attr(q->req, userpass.pass,
1741 	    sizeof(userpass.pass), radius_query_client_secret(q)) == 0)
1742 		userpass.has_pass = true;
1743 	else
1744 		userpass.has_pass = false;
1745 	if (radius_get_string_attr(q->req, RADIUS_TYPE_USER_NAME,
1746 	    userpass.user, sizeof(userpass.user)) != 0) {
1747 		log_warnx("q=%u no User-Name attribute", q->id);
1748 		goto on_error;
1749 	}
1750 	imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_USERPASS, 0, 0, -1,
1751 	    &userpass, sizeof(userpass));
1752 	radiusd_module_reset_ev_handler(module);
1753 	return;
1754 on_error:
1755 	radiusd_access_request_aborted(q);
1756 }
1757 
1758 static void
1759 radiusd_module_access_request(struct radiusd_module *module,
1760     struct radius_query *q)
1761 {
1762 	RADIUS_PACKET	*radpkt;
1763 	char		 pass[256];
1764 
1765 	if ((radpkt = radius_convert_packet(radius_get_data(q->req),
1766 	    radius_get_length(q->req))) == NULL) {
1767 		log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
1768 		    module->name);
1769 		radiusd_access_request_aborted(q);
1770 		return;
1771 	}
1772 	if (radius_get_user_password_attr(radpkt, pass, sizeof(pass),
1773 	    q->client->secret) == 0) {
1774 		radius_del_attr_all(radpkt, RADIUS_TYPE_USER_PASSWORD);
1775 		(void)radius_put_raw_attr(radpkt, RADIUS_TYPE_USER_PASSWORD,
1776 		    pass, strlen(pass));
1777 	}
1778 	if (imsg_compose_radius_packet(&module->ibuf,
1779 	    IMSG_RADIUSD_MODULE_ACCSREQ, q->id, radpkt) == -1) {
1780 		log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
1781 		    module->name);
1782 		radiusd_access_request_aborted(q);
1783 	}
1784 	radiusd_module_reset_ev_handler(module);
1785 	radius_delete_packet(radpkt);
1786 }
1787 
1788 static void
1789 radiusd_module_next_response(struct radiusd_module *module,
1790     struct radius_query *q, RADIUS_PACKET *pkt)
1791 {
1792 	if (imsg_compose_radius_packet(&module->ibuf,
1793 	    IMSG_RADIUSD_MODULE_NEXTRES, q->id, pkt) == -1) {
1794 		log_warn("q=%u Could not send NEXTRES to `%s'", q->id,
1795 		    module->name);
1796 		radiusd_access_request_aborted(q);
1797 	}
1798 	radiusd_module_reset_ev_handler(module);
1799 }
1800 
1801 static void
1802 radiusd_module_request_decoration(struct radiusd_module *module,
1803     struct radius_query *q)
1804 {
1805 	if (module->fd < 0) {
1806 		log_warnx("q=%u Could not send REQDECO to `%s': module is "
1807 		    "not running?", q->id, module->name);
1808 		radiusd_access_request_aborted(q);
1809 		return;
1810 	}
1811 	if (imsg_compose_radius_packet(&module->ibuf,
1812 	    IMSG_RADIUSD_MODULE_REQDECO, q->id, q->req) == -1) {
1813 		log_warn("q=%u Could not send REQDECO to `%s'", q->id,
1814 		    module->name);
1815 		radiusd_access_request_aborted(q);
1816 		return;
1817 	}
1818 	RADIUSD_ASSERT(q->deco != NULL);
1819 	q->deco->type = IMSG_RADIUSD_MODULE_REQDECO;
1820 	radiusd_module_reset_ev_handler(module);
1821 }
1822 
1823 static void
1824 radiusd_module_response_decoration(struct radiusd_module *module,
1825     struct radius_query *q)
1826 {
1827 	if (module->fd < 0) {
1828 		log_warnx("q=%u Could not send RESDECO to `%s': module is "
1829 		    "not running?", q->id, module->name);
1830 		radiusd_access_request_aborted(q);
1831 		return;
1832 	}
1833 	if (imsg_compose_radius_packet(&module->ibuf,
1834 	    IMSG_RADIUSD_MODULE_RESDECO0_REQ, q->id, q->req) == -1) {
1835 		log_warn("q=%u Could not send RESDECO0_REQ to `%s'", q->id,
1836 		    module->name);
1837 		radiusd_access_request_aborted(q);
1838 		return;
1839 	}
1840 	if (imsg_compose_radius_packet(&module->ibuf,
1841 	    IMSG_RADIUSD_MODULE_RESDECO, q->id, q->res) == -1) {
1842 		log_warn("q=%u Could not send RESDECO to `%s'", q->id,
1843 		    module->name);
1844 		radiusd_access_request_aborted(q);
1845 		return;
1846 	}
1847 	RADIUSD_ASSERT(q->deco != NULL);
1848 	q->deco->type = IMSG_RADIUSD_MODULE_RESDECO;
1849 	radiusd_module_reset_ev_handler(module);
1850 }
1851 
1852 static void
1853 radiusd_module_account_request(struct radiusd_module *module,
1854     struct radius_query *q)
1855 {
1856 	RADIUS_PACKET				*radpkt;
1857 
1858 	if ((radpkt = radius_convert_packet(radius_get_data(q->req),
1859 	    radius_get_length(q->req))) == NULL) {
1860 		log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
1861 		    module->name);
1862 		radiusd_access_request_aborted(q);
1863 		return;
1864 	}
1865 	if (imsg_compose_radius_packet(&module->ibuf,
1866 	    IMSG_RADIUSD_MODULE_ACCTREQ, q->id, radpkt) == -1) {
1867 		log_warn("q=%u Could not send ACCTREQ to `%s'", q->id,
1868 		    module->name);
1869 		radiusd_access_request_aborted(q);
1870 	}
1871 	radiusd_module_reset_ev_handler(module);
1872 	radius_delete_packet(radpkt);
1873 }
1874 
1875 static int
1876 imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id,
1877     RADIUS_PACKET *radpkt)
1878 {
1879 	struct radiusd_module_radpkt_arg	 arg;
1880 	int					 off = 0, len, siz;
1881 	struct iovec				 iov[2];
1882 	const u_char				*pkt;
1883 
1884 	pkt = radius_get_data(radpkt);
1885 	len = radius_get_length(radpkt);
1886 	memset(&arg, 0, sizeof(arg));
1887 	arg.q_id = q_id;
1888 	arg.pktlen = len;
1889 	while (off < len) {
1890 		siz = MAX_IMSGSIZE - sizeof(arg);
1891 		if (len - off > siz)
1892 			arg.final = false;
1893 		else {
1894 			arg.final = true;
1895 			siz = len - off;
1896 		}
1897 		iov[0].iov_base = &arg;
1898 		iov[0].iov_len = sizeof(arg);
1899 		iov[1].iov_base = (caddr_t)pkt + off;
1900 		iov[1].iov_len = siz;
1901 		if (imsg_composev(ibuf, type, 0, 0, -1, iov, 2) == -1)
1902 			return (-1);
1903 		off += siz;
1904 	}
1905 	return (0);
1906 }
1907 
1908 static void
1909 close_stdio(void)
1910 {
1911 	int	fd;
1912 
1913 	if ((fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
1914 		dup2(fd, STDIN_FILENO);
1915 		dup2(fd, STDOUT_FILENO);
1916 		dup2(fd, STDERR_FILENO);
1917 		if (fd > STDERR_FILENO)
1918 			close(fd);
1919 	}
1920 }
1921 
1922 /***********************************************************************
1923  * imsg_event
1924  ***********************************************************************/
1925 struct iovec;
1926 
1927 void
1928 imsg_event_add(struct imsgev *iev)
1929 {
1930 	iev->events = EV_READ;
1931 	if (imsgbuf_queuelen(&iev->ibuf) > 0)
1932 		iev->events |= EV_WRITE;
1933 
1934 	event_del(&iev->ev);
1935 	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
1936 	event_add(&iev->ev, NULL);
1937 }
1938 
1939 int
1940 imsg_compose_event(struct imsgev *iev, uint32_t type, uint32_t peerid,
1941     pid_t pid, int fd, void *data, size_t datalen)
1942 {
1943 	int	ret;
1944 
1945 	if ((ret = imsg_compose(&iev->ibuf, type, peerid,
1946 	    pid, fd, data, datalen)) != -1)
1947 		imsg_event_add(iev);
1948 	return (ret);
1949 }
1950 
1951 int
1952 imsg_composev_event(struct imsgev *iev, uint32_t type, uint32_t peerid,
1953     pid_t pid, int fd, struct iovec *iov, int niov)
1954 {
1955 	int	ret;
1956 
1957 	if ((ret = imsg_composev(&iev->ibuf, type, peerid,
1958 	    pid, fd, iov, niov)) != -1)
1959 		imsg_event_add(iev);
1960 	return (ret);
1961 }
1962