xref: /openbsd-src/usr.sbin/radiusd/radiusd.c (revision dcc91c2622318df8f66a9bca2d2864253df1bfc3)
1 /*	$OpenBSD: radiusd.c,v 1.55 2024/08/14 07:06:50 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("unkown child process pid=%d exited "
950 				    "with status %d", (int)pid,
951 				     WEXITSTATUS(status));
952 			else
953 				log_warnx("unkown 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 	imsg_init(&module->ibuf, module->fd);
1204 
1205 	if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0 ||
1206 	    (n = imsg_get(&module->ibuf, &imsg)) <= 0) {
1207 		log_warnx("Could not load module `%s': module didn't "
1208 		    "respond", name);
1209 		goto on_error;
1210 	}
1211 	if (imsg.hdr.type != IMSG_RADIUSD_MODULE_LOAD) {
1212 		imsg_free(&imsg);
1213 		log_warnx("Could not load module `%s': unknown imsg type=%d",
1214 		    name, imsg.hdr.type);
1215 		goto on_error;
1216 	}
1217 
1218 	module->capabilities =
1219 	    ((struct radiusd_module_load_arg *)imsg.data)->cap;
1220 
1221 	log_debug("Loaded module `%s' successfully.  pid=%d", module->name,
1222 	    module->pid);
1223 	imsg_free(&imsg);
1224 
1225 	return (module);
1226 
1227 on_error:
1228 	free(module);
1229 	if (pairsock[0] >= 0)
1230 		close(pairsock[0]);
1231 	if (pairsock[1] >= 0)
1232 		close(pairsock[1]);
1233 
1234 	return (NULL);
1235 }
1236 
1237 void
1238 radiusd_module_start(struct radiusd_module *module)
1239 {
1240 	int		 datalen;
1241 	struct imsg	 imsg;
1242 	struct timeval	 tv = { 0, 0 };
1243 
1244 	RADIUSD_ASSERT(module->fd >= 0);
1245 	imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_START, 0, 0, -1,
1246 	    NULL, 0);
1247 	imsg_sync_flush(&module->ibuf, MODULE_IO_TIMEOUT);
1248 	if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0 ||
1249 	    imsg_get(&module->ibuf, &imsg) <= 0) {
1250 		log_warnx("Module `%s' could not start: no response",
1251 		    module->name);
1252 		goto on_fail;
1253 	}
1254 
1255 	datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
1256 	if (imsg.hdr.type != IMSG_OK) {
1257 		if (imsg.hdr.type == IMSG_NG) {
1258 			if (datalen > 0)
1259 				log_warnx("Module `%s' could not start: %s",
1260 				    module->name, (char *)imsg.data);
1261 			else
1262 				log_warnx("Module `%s' could not start",
1263 				    module->name);
1264 		} else
1265 			log_warnx("Module `%s' could not started: module "
1266 			    "returned unknown message type %d", module->name,
1267 			    imsg.hdr.type);
1268 		goto on_fail;
1269 	}
1270 
1271 	event_set(&module->ev, module->fd, EV_READ, radiusd_module_on_imsg_io,
1272 	    module);
1273 	event_add(&module->ev, &tv);
1274 	log_debug("Module `%s' started successfully", module->name);
1275 
1276 	return;
1277 on_fail:
1278 	radiusd_module_close(module);
1279 	return;
1280 }
1281 
1282 void
1283 radiusd_module_stop(struct radiusd_module *module)
1284 {
1285 	module->stopped = true;
1286 
1287 	if (module->secret != NULL) {
1288 		freezero(module->secret, strlen(module->secret));
1289 		module->secret = NULL;
1290 	}
1291 
1292 	if (module->fd >= 0) {
1293 		imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_STOP, 0, 0, -1,
1294 		    NULL, 0);
1295 		radiusd_module_reset_ev_handler(module);
1296 	}
1297 }
1298 
1299 static void
1300 radiusd_module_close(struct radiusd_module *module)
1301 {
1302 	if (module->fd >= 0) {
1303 		event_del(&module->ev);
1304 		imsg_clear(&module->ibuf);
1305 		close(module->fd);
1306 		module->fd = -1;
1307 	}
1308 }
1309 
1310 void
1311 radiusd_module_unload(struct radiusd_module *module)
1312 {
1313 	free(module->radpkt);
1314 	radiusd_module_close(module);
1315 	free(module);
1316 }
1317 
1318 static void
1319 radiusd_module_on_imsg_io(int fd, short evmask, void *ctx)
1320 {
1321 	struct radiusd_module	*module = ctx;
1322 	int			 ret;
1323 
1324 	if (evmask & EV_WRITE)
1325 		module->writeready = true;
1326 
1327 	if (evmask & EV_READ) {
1328 		if (radiusd_module_imsg_read(module) == -1)
1329 			goto on_error;
1330 	}
1331 
1332 	while (module->writeready && module->ibuf.w.queued) {
1333 		ret = msgbuf_write(&module->ibuf.w);
1334 		if (ret > 0)
1335 			continue;
1336 		module->writeready = false;
1337 		if (ret == 0 && errno == EAGAIN)
1338 			break;
1339 		log_warn("Failed to write to module `%s': msgbuf_write()",
1340 		    module->name);
1341 		goto on_error;
1342 	}
1343 	radiusd_module_reset_ev_handler(module);
1344 
1345 	return;
1346 on_error:
1347 	radiusd_module_close(module);
1348 }
1349 
1350 static void
1351 radiusd_module_reset_ev_handler(struct radiusd_module *module)
1352 {
1353 	short		 evmask;
1354 	struct timeval	*tvp = NULL, tv = { 0, 0 };
1355 
1356 	RADIUSD_ASSERT(module->fd >= 0);
1357 	event_del(&module->ev);
1358 
1359 	evmask = EV_READ;
1360 	if (module->ibuf.w.queued) {
1361 		if (!module->writeready)
1362 			evmask |= EV_WRITE;
1363 		else
1364 			tvp = &tv;	/* fire immediately */
1365 	}
1366 
1367 	/* module stopped and no event handler is set */
1368 	if (evmask & EV_WRITE && tvp == NULL && module->stopped) {
1369 		/* stop requested and no more to write */
1370 		radiusd_module_close(module);
1371 		return;
1372 	}
1373 
1374 	event_set(&module->ev, module->fd, evmask, radiusd_module_on_imsg_io,
1375 	    module);
1376 	if (event_add(&module->ev, tvp) == -1) {
1377 		log_warn("Could not set event handlers for module `%s': "
1378 		    "event_add()", module->name);
1379 		radiusd_module_close(module);
1380 	}
1381 }
1382 
1383 static int
1384 radiusd_module_imsg_read(struct radiusd_module *module)
1385 {
1386 	int		 n;
1387 	struct imsg	 imsg;
1388 
1389 	if ((n = imsg_read(&module->ibuf)) == -1 || n == 0) {
1390 		if (n == -1 && errno == EAGAIN)
1391 			return (0);
1392 		if (n == -1)
1393 			log_warn("Receiving a message from module `%s' "
1394 			    "failed: imsg_read", module->name);
1395 		/* else closed */
1396 		radiusd_module_close(module);
1397 		return (-1);
1398 	}
1399 	for (;;) {
1400 		if ((n = imsg_get(&module->ibuf, &imsg)) == -1) {
1401 			log_warn("Receiving a message from module `%s' failed: "
1402 			    "imsg_get", module->name);
1403 			return (-1);
1404 		}
1405 		if (n == 0)
1406 			return (0);
1407 		radiusd_module_imsg(module, &imsg);
1408 		imsg_free(&imsg);
1409 	}
1410 
1411 	return (0);
1412 }
1413 
1414 static void
1415 radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
1416 {
1417 	int			 datalen;
1418 	struct radius_query	*q;
1419 	u_int			 q_id;
1420 
1421 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
1422 	switch (imsg->hdr.type) {
1423 	case IMSG_RADIUSD_MODULE_NOTIFY_SECRET:
1424 		if (datalen > 0) {
1425 			module->secret = strdup(imsg->data);
1426 			if (module->secret == NULL)
1427 				log_warn("Could not handle NOTIFY_SECRET "
1428 				    "from `%s'", module->name);
1429 		}
1430 		break;
1431 	case IMSG_RADIUSD_MODULE_USERPASS_OK:
1432 	case IMSG_RADIUSD_MODULE_USERPASS_FAIL:
1433 	    {
1434 		char			*msg = NULL;
1435 		const char		*msgtypestr;
1436 
1437 		msgtypestr = (imsg->hdr.type == IMSG_RADIUSD_MODULE_USERPASS_OK)
1438 		    ? "USERPASS_OK" : "USERPASS_NG";
1439 
1440 		q_id = *(u_int *)imsg->data;
1441 		if (datalen > (ssize_t)sizeof(u_int))
1442 			msg = (char *)(((u_int *)imsg->data) + 1);
1443 
1444 		q = radiusd_find_query(module->radiusd, q_id);
1445 		if (q == NULL) {
1446 			log_warnx("Received %s from `%s', but query id=%u "
1447 			    "unknown", msgtypestr, module->name, q_id);
1448 			break;
1449 		}
1450 
1451 		if ((q->res = radius_new_response_packet(
1452 		    (imsg->hdr.type == IMSG_RADIUSD_MODULE_USERPASS_OK)
1453 		    ? RADIUS_CODE_ACCESS_ACCEPT : RADIUS_CODE_ACCESS_REJECT,
1454 		    q->req)) == NULL) {
1455 			log_warn("radius_new_response_packet() failed");
1456 			radiusd_access_request_aborted(q);
1457 		} else {
1458 			if (msg)
1459 				radius_put_string_attr(q->res,
1460 				    RADIUS_TYPE_REPLY_MESSAGE, msg);
1461 			radius_set_response_authenticator(q->res,
1462 			    radius_query_client_secret(q));
1463 			radiusd_access_request_answer(q);
1464 		}
1465 		break;
1466 	    }
1467 	case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1468 	case IMSG_RADIUSD_MODULE_ACCSREQ_NEXT:
1469 	case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1470 	case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1471 	    {
1472 		static struct radiusd_module_radpkt_arg *ans;
1473 		const char *typestr = "unknown";
1474 
1475 		switch (imsg->hdr.type) {
1476 		case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1477 			typestr = "ACCSREQ_ANSWER";
1478 			break;
1479 		case IMSG_RADIUSD_MODULE_ACCSREQ_NEXT:
1480 			typestr = "ACCSREQ_NEXT";
1481 			break;
1482 		case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1483 			typestr = "REQDECO_DONE";
1484 			break;
1485 		case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1486 			typestr = "RESDECO_DONE";
1487 			break;
1488 		}
1489 
1490 		if (datalen <
1491 		    (ssize_t)sizeof(struct radiusd_module_radpkt_arg)) {
1492 			log_warnx("Received %s message, but length is wrong",
1493 			    typestr);
1494 			break;
1495 		}
1496 		q_id = ((struct radiusd_module_radpkt_arg *)imsg->data)->q_id;
1497 		q = radiusd_find_query(module->radiusd, q_id);
1498 		if (q == NULL) {
1499 			log_warnx("Received %s from %s, but query id=%u "
1500 			    "unknown", typestr, module->name, q_id);
1501 			break;
1502 		}
1503 		if ((ans = radiusd_module_recv_radpkt(module, imsg,
1504 		    imsg->hdr.type, typestr)) != NULL) {
1505 			RADIUS_PACKET *radpkt = NULL;
1506 
1507 			if (module->radpktoff > 0 &&
1508 			    (radpkt = radius_convert_packet(
1509 			    module->radpkt, module->radpktoff)) == NULL) {
1510 				log_warn("q=%u radius_convert_packet() failed",
1511 				    q->id);
1512 				radiusd_access_request_aborted(q);
1513 				break;
1514 			}
1515 			module->radpktoff = 0;
1516 			switch (imsg->hdr.type) {
1517 			case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1518 				if (q->deco == NULL || q->deco->type !=
1519 				    IMSG_RADIUSD_MODULE_REQDECO) {
1520 					log_warnx("q=%u received %s but not "
1521 					    "requested", q->id, typestr);
1522 					if (radpkt != NULL)
1523 						radius_delete_packet(radpkt);
1524 					break;
1525 				}
1526 				if (radpkt != NULL) {
1527 					radius_delete_packet(q->req);
1528 					q->req = radpkt;
1529 				}
1530 				raidus_query_access_request(q);
1531 				break;
1532 			case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1533 				if (radpkt == NULL) {
1534 					log_warnx("q=%u wrong pkt from module",
1535 					    q->id);
1536 					radiusd_access_request_aborted(q);
1537 					break;
1538 				}
1539 				q->res = radpkt;
1540 				radiusd_access_request_answer(q);
1541 				break;
1542 			case IMSG_RADIUSD_MODULE_ACCSREQ_NEXT:
1543 				if (radpkt == NULL) {
1544 					log_warnx("q=%u wrong pkt from module",
1545 					    q->id);
1546 					radiusd_access_request_aborted(q);
1547 					break;
1548 				}
1549 				radiusd_access_request_next(q, radpkt);
1550 				break;
1551 			case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1552 				if (q->deco == NULL || q->deco->type !=
1553 				    IMSG_RADIUSD_MODULE_RESDECO) {
1554 					log_warnx("q=%u received %s but not "
1555 					    "requested", q->id, typestr);
1556 					if (radpkt != NULL)
1557 						radius_delete_packet(radpkt);
1558 					break;
1559 				}
1560 				if (radpkt != NULL) {
1561 					radius_delete_packet(q->res);
1562 					radius_set_request_packet(radpkt,
1563 					    q->req);
1564 					q->res = radpkt;
1565 				}
1566 				radius_query_access_response(q);
1567 				break;
1568 			}
1569 		}
1570 		break;
1571 	    }
1572 	case IMSG_RADIUSD_MODULE_ACCSREQ_ABORTED:
1573 	    {
1574 		if (datalen < (ssize_t)sizeof(u_int)) {
1575 			log_warnx("Received ACCSREQ_ABORTED message, but "
1576 			    "length is wrong");
1577 			break;
1578 		}
1579 		q_id = *((u_int *)imsg->data);
1580 		q = radiusd_find_query(module->radiusd, q_id);
1581 		if (q == NULL) {
1582 			log_warnx("Received ACCSREQ_ABORT from %s, but query "
1583 			    "id=%u unknown", module->name, q_id);
1584 			break;
1585 		}
1586 		radiusd_access_request_aborted(q);
1587 		break;
1588 	    }
1589 	case IMSG_RADIUSD_MODULE_CTRL_BIND:
1590 		control_conn_bind(imsg->hdr.peerid, module->name);
1591 		break;
1592 	default:
1593 		if (imsg->hdr.peerid != 0)
1594 			control_imsg_relay(imsg);
1595 		else
1596 			RADIUSD_DBG(("Unhandled imsg type=%d from %s",
1597 			    imsg->hdr.type, module->name));
1598 	}
1599 }
1600 
1601 static struct radiusd_module_radpkt_arg *
1602 radiusd_module_recv_radpkt(struct radiusd_module *module, struct imsg *imsg,
1603     uint32_t imsg_type, const char *type_str)
1604 {
1605 	struct radiusd_module_radpkt_arg	*ans;
1606 	int					 datalen, chunklen;
1607 
1608 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
1609 	ans = (struct radiusd_module_radpkt_arg *)imsg->data;
1610 	if (module->radpktsiz < ans->pktlen) {
1611 		u_char *nradpkt;
1612 		if ((nradpkt = realloc(module->radpkt, ans->pktlen)) == NULL) {
1613 			log_warn("Could not handle received %s message from "
1614 			    "`%s'", type_str, module->name);
1615 			goto on_fail;
1616 		}
1617 		module->radpkt = nradpkt;
1618 		module->radpktsiz = ans->pktlen;
1619 	}
1620 	chunklen = datalen - sizeof(struct radiusd_module_radpkt_arg);
1621 	if (chunklen > module->radpktsiz - module->radpktoff) {
1622 		log_warnx("Could not handle received %s message from `%s': "
1623 		    "received length is too big", type_str, module->name);
1624 		goto on_fail;
1625 	}
1626 	if (chunklen > 0) {
1627 		memcpy(module->radpkt + module->radpktoff,
1628 		    (caddr_t)(ans + 1), chunklen);
1629 		module->radpktoff += chunklen;
1630 	}
1631 	if (!ans->final)
1632 		return (NULL);	/* again */
1633 	if (module->radpktoff != ans->pktlen) {
1634 		log_warnx("Could not handle received %s message from `%s': "
1635 		    "length is mismatch", type_str, module->name);
1636 		goto on_fail;
1637 	}
1638 
1639 	return (ans);
1640 on_fail:
1641 	module->radpktoff = 0;
1642 	return (NULL);
1643 }
1644 
1645 int
1646 radiusd_module_set(struct radiusd_module *module, const char *name,
1647     int argc, char * const * argv)
1648 {
1649 	struct radiusd_module_set_arg	 arg;
1650 	struct radiusd_module_object	*val;
1651 	int				 i, niov = 0;
1652 	u_char				*buf = NULL, *buf0;
1653 	ssize_t				 n;
1654 	size_t				 bufsiz = 0, bufoff = 0, bufsiz0;
1655 	size_t				 vallen, valsiz;
1656 	struct iovec			 iov[2];
1657 	struct imsg			 imsg;
1658 
1659 	memset(&arg, 0, sizeof(arg));
1660 	arg.nparamval = argc;
1661 	strlcpy(arg.paramname, name, sizeof(arg.paramname));
1662 
1663 	iov[niov].iov_base = &arg;
1664 	iov[niov].iov_len = sizeof(struct radiusd_module_set_arg);
1665 	niov++;
1666 
1667 	for (i = 0; i < argc; i++) {
1668 		vallen = strlen(argv[i]) + 1;
1669 		valsiz = sizeof(struct radiusd_module_object) + vallen;
1670 		if (bufsiz < bufoff + valsiz) {
1671 			bufsiz0 = bufoff + valsiz + 128;
1672 			if ((buf0 = realloc(buf, bufsiz0)) == NULL) {
1673 				log_warn("Failed to set config parameter to "
1674 				    "module `%s': realloc", module->name);
1675 				goto on_error;
1676 			}
1677 			buf = buf0;
1678 			bufsiz = bufsiz0;
1679 			memset(buf + bufoff, 0, bufsiz - bufoff);
1680 		}
1681 		val = (struct radiusd_module_object *)(buf + bufoff);
1682 		val->size = valsiz;
1683 		memcpy(val + 1, argv[i], vallen);
1684 
1685 		bufoff += valsiz;
1686 	}
1687 	iov[niov].iov_base = buf;
1688 	iov[niov].iov_len = bufoff;
1689 	niov++;
1690 
1691 	if (imsg_composev(&module->ibuf, IMSG_RADIUSD_MODULE_SET_CONFIG, 0, 0,
1692 	    -1, iov, niov) == -1) {
1693 		log_warn("Failed to set config parameter to module `%s': "
1694 		    "imsg_composev", module->name);
1695 		goto on_error;
1696 	}
1697 	if (imsg_sync_flush(&module->ibuf, MODULE_IO_TIMEOUT) == -1) {
1698 		log_warn("Failed to set config parameter to module `%s': "
1699 		    "imsg_flush_timeout", module->name);
1700 		goto on_error;
1701 	}
1702 	for (;;) {
1703 		if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0) {
1704 			log_warn("Failed to get reply from module `%s': "
1705 			    "imsg_sync_read", module->name);
1706 			goto on_error;
1707 		}
1708 		if ((n = imsg_get(&module->ibuf, &imsg)) > 0)
1709 			break;
1710 		if (n < 0) {
1711 			log_warn("Failed to get reply from module `%s': "
1712 			    "imsg_get", module->name);
1713 			goto on_error;
1714 		}
1715 	}
1716 	if (imsg.hdr.type == IMSG_NG) {
1717 		log_warnx("Could not set `%s' for module `%s': %s", name,
1718 		    module->name, (char *)imsg.data);
1719 		goto on_error;
1720 	} else if (imsg.hdr.type != IMSG_OK) {
1721 		imsg_free(&imsg);
1722 		log_warnx("Failed to get reply from module `%s': "
1723 		    "unknown imsg type=%d", module->name, imsg.hdr.type);
1724 		goto on_error;
1725 	}
1726 	imsg_free(&imsg);
1727 
1728 	free(buf);
1729 	return (0);
1730 
1731 on_error:
1732 	free(buf);
1733 	return (-1);
1734 }
1735 
1736 static void
1737 radiusd_module_userpass(struct radiusd_module *module, struct radius_query *q)
1738 {
1739 	struct radiusd_module_userpass_arg userpass;
1740 
1741 	memset(&userpass, 0, sizeof(userpass));
1742 	userpass.q_id = q->id;
1743 
1744 	if (radius_get_user_password_attr(q->req, userpass.pass,
1745 	    sizeof(userpass.pass), radius_query_client_secret(q)) == 0)
1746 		userpass.has_pass = true;
1747 	else
1748 		userpass.has_pass = false;
1749 	if (radius_get_string_attr(q->req, RADIUS_TYPE_USER_NAME,
1750 	    userpass.user, sizeof(userpass.user)) != 0) {
1751 		log_warnx("q=%u no User-Name attribute", q->id);
1752 		goto on_error;
1753 	}
1754 	imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_USERPASS, 0, 0, -1,
1755 	    &userpass, sizeof(userpass));
1756 	radiusd_module_reset_ev_handler(module);
1757 	return;
1758 on_error:
1759 	radiusd_access_request_aborted(q);
1760 }
1761 
1762 static void
1763 radiusd_module_access_request(struct radiusd_module *module,
1764     struct radius_query *q)
1765 {
1766 	RADIUS_PACKET	*radpkt;
1767 	char		 pass[256];
1768 
1769 	if ((radpkt = radius_convert_packet(radius_get_data(q->req),
1770 	    radius_get_length(q->req))) == NULL) {
1771 		log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
1772 		    module->name);
1773 		radiusd_access_request_aborted(q);
1774 		return;
1775 	}
1776 	if (radius_get_user_password_attr(radpkt, pass, sizeof(pass),
1777 	    q->client->secret) == 0) {
1778 		radius_del_attr_all(radpkt, RADIUS_TYPE_USER_PASSWORD);
1779 		(void)radius_put_raw_attr(radpkt, RADIUS_TYPE_USER_PASSWORD,
1780 		    pass, strlen(pass));
1781 	}
1782 	if (imsg_compose_radius_packet(&module->ibuf,
1783 	    IMSG_RADIUSD_MODULE_ACCSREQ, q->id, radpkt) == -1) {
1784 		log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
1785 		    module->name);
1786 		radiusd_access_request_aborted(q);
1787 	}
1788 	radiusd_module_reset_ev_handler(module);
1789 	radius_delete_packet(radpkt);
1790 }
1791 
1792 static void
1793 radiusd_module_next_response(struct radiusd_module *module,
1794     struct radius_query *q, RADIUS_PACKET *pkt)
1795 {
1796 	if (imsg_compose_radius_packet(&module->ibuf,
1797 	    IMSG_RADIUSD_MODULE_NEXTRES, q->id, pkt) == -1) {
1798 		log_warn("q=%u Could not send NEXTRES to `%s'", q->id,
1799 		    module->name);
1800 		radiusd_access_request_aborted(q);
1801 	}
1802 	radiusd_module_reset_ev_handler(module);
1803 }
1804 
1805 static void
1806 radiusd_module_request_decoration(struct radiusd_module *module,
1807     struct radius_query *q)
1808 {
1809 	if (module->fd < 0) {
1810 		log_warnx("q=%u Could not send REQDECO to `%s': module is "
1811 		    "not running?", q->id, module->name);
1812 		radiusd_access_request_aborted(q);
1813 		return;
1814 	}
1815 	if (imsg_compose_radius_packet(&module->ibuf,
1816 	    IMSG_RADIUSD_MODULE_REQDECO, q->id, q->req) == -1) {
1817 		log_warn("q=%u Could not send REQDECO to `%s'", q->id,
1818 		    module->name);
1819 		radiusd_access_request_aborted(q);
1820 		return;
1821 	}
1822 	RADIUSD_ASSERT(q->deco != NULL);
1823 	q->deco->type = IMSG_RADIUSD_MODULE_REQDECO;
1824 	radiusd_module_reset_ev_handler(module);
1825 }
1826 
1827 static void
1828 radiusd_module_response_decoration(struct radiusd_module *module,
1829     struct radius_query *q)
1830 {
1831 	if (module->fd < 0) {
1832 		log_warnx("q=%u Could not send RESDECO to `%s': module is "
1833 		    "not running?", q->id, module->name);
1834 		radiusd_access_request_aborted(q);
1835 		return;
1836 	}
1837 	if (imsg_compose_radius_packet(&module->ibuf,
1838 	    IMSG_RADIUSD_MODULE_RESDECO0_REQ, q->id, q->req) == -1) {
1839 		log_warn("q=%u Could not send RESDECO0_REQ to `%s'", q->id,
1840 		    module->name);
1841 		radiusd_access_request_aborted(q);
1842 		return;
1843 	}
1844 	if (imsg_compose_radius_packet(&module->ibuf,
1845 	    IMSG_RADIUSD_MODULE_RESDECO, q->id, q->res) == -1) {
1846 		log_warn("q=%u Could not send RESDECO to `%s'", q->id,
1847 		    module->name);
1848 		radiusd_access_request_aborted(q);
1849 		return;
1850 	}
1851 	RADIUSD_ASSERT(q->deco != NULL);
1852 	q->deco->type = IMSG_RADIUSD_MODULE_RESDECO;
1853 	radiusd_module_reset_ev_handler(module);
1854 }
1855 
1856 static void
1857 radiusd_module_account_request(struct radiusd_module *module,
1858     struct radius_query *q)
1859 {
1860 	RADIUS_PACKET				*radpkt;
1861 
1862 	if ((radpkt = radius_convert_packet(radius_get_data(q->req),
1863 	    radius_get_length(q->req))) == NULL) {
1864 		log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
1865 		    module->name);
1866 		radiusd_access_request_aborted(q);
1867 		return;
1868 	}
1869 	if (imsg_compose_radius_packet(&module->ibuf,
1870 	    IMSG_RADIUSD_MODULE_ACCTREQ, q->id, radpkt) == -1) {
1871 		log_warn("q=%u Could not send ACCTREQ to `%s'", q->id,
1872 		    module->name);
1873 		radiusd_access_request_aborted(q);
1874 	}
1875 	radiusd_module_reset_ev_handler(module);
1876 	radius_delete_packet(radpkt);
1877 }
1878 
1879 static int
1880 imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id,
1881     RADIUS_PACKET *radpkt)
1882 {
1883 	struct radiusd_module_radpkt_arg	 arg;
1884 	int					 off = 0, len, siz;
1885 	struct iovec				 iov[2];
1886 	const u_char				*pkt;
1887 
1888 	pkt = radius_get_data(radpkt);
1889 	len = radius_get_length(radpkt);
1890 	memset(&arg, 0, sizeof(arg));
1891 	arg.q_id = q_id;
1892 	arg.pktlen = len;
1893 	while (off < len) {
1894 		siz = MAX_IMSGSIZE - sizeof(arg);
1895 		if (len - off > siz)
1896 			arg.final = false;
1897 		else {
1898 			arg.final = true;
1899 			siz = len - off;
1900 		}
1901 		iov[0].iov_base = &arg;
1902 		iov[0].iov_len = sizeof(arg);
1903 		iov[1].iov_base = (caddr_t)pkt + off;
1904 		iov[1].iov_len = siz;
1905 		if (imsg_composev(ibuf, type, 0, 0, -1, iov, 2) == -1)
1906 			return (-1);
1907 		off += siz;
1908 	}
1909 	return (0);
1910 }
1911 
1912 static void
1913 close_stdio(void)
1914 {
1915 	int	fd;
1916 
1917 	if ((fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
1918 		dup2(fd, STDIN_FILENO);
1919 		dup2(fd, STDOUT_FILENO);
1920 		dup2(fd, STDERR_FILENO);
1921 		if (fd > STDERR_FILENO)
1922 			close(fd);
1923 	}
1924 }
1925 
1926 /***********************************************************************
1927  * imsg_event
1928  ***********************************************************************/
1929 struct iovec;
1930 
1931 void
1932 imsg_event_add(struct imsgev *iev)
1933 {
1934 	iev->events = EV_READ;
1935 	if (iev->ibuf.w.queued)
1936 		iev->events |= EV_WRITE;
1937 
1938 	event_del(&iev->ev);
1939 	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
1940 	event_add(&iev->ev, NULL);
1941 }
1942 
1943 int
1944 imsg_compose_event(struct imsgev *iev, uint32_t type, uint32_t peerid,
1945     pid_t pid, int fd, void *data, size_t datalen)
1946 {
1947 	int	ret;
1948 
1949 	if ((ret = imsg_compose(&iev->ibuf, type, peerid,
1950 	    pid, fd, data, datalen)) != -1)
1951 		imsg_event_add(iev);
1952 	return (ret);
1953 }
1954 
1955 int
1956 imsg_composev_event(struct imsgev *iev, uint32_t type, uint32_t peerid,
1957     pid_t pid, int fd, struct iovec *iov, int niov)
1958 {
1959 	int	ret;
1960 
1961 	if ((ret = imsg_composev(&iev->ibuf, type, peerid,
1962 	    pid, fd, iov, niov)) != -1)
1963 		imsg_event_add(iev);
1964 	return (ret);
1965 }
1966