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
usage(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
main(int argc,char * argv[])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
radiusd_start(struct radiusd * radiusd)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
radiusd_stop(struct radiusd * radiusd)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
radiusd_free(struct radiusd * radiusd)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
radiusd_listen_on_event(int fd,short evmask,void * ctx)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
radiusd_listen_handle_packet(struct radiusd_listen * listn,RADIUS_PACKET * packet,struct sockaddr * peer,socklen_t peerlen)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
raidus_query_access_request(struct radius_query * q)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
radius_query_access_response(struct radius_query * q)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
raidus_query_accounting_request(struct radiusd_accounting * accounting,struct radius_query * q)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
radius_query_accounting_response(struct radius_query * q)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 *
radius_query_client_secret(struct radius_query * q)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
radiusd_access_request_answer(struct radius_query * q)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
radiusd_access_request_next(struct radius_query * q,RADIUS_PACKET * pkt)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
radiusd_access_request_aborted(struct radius_query * q)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
radiusd_on_sigterm(int fd,short evmask,void * ctx)902 radiusd_on_sigterm(int fd, short evmask, void *ctx)
903 {
904 log_info("Received SIGTERM");
905 event_loopbreak();
906 }
907
908 static void
radiusd_on_sigint(int fd,short evmask,void * ctx)909 radiusd_on_sigint(int fd, short evmask, void *ctx)
910 {
911 log_info("Received SIGINT");
912 event_loopbreak();
913 }
914
915 static void
radiusd_on_sighup(int fd,short evmask,void * ctx)916 radiusd_on_sighup(int fd, short evmask, void *ctx)
917 {
918 log_info("Received SIGHUP");
919 }
920
921 static void
radiusd_on_sigchld(int fd,short evmask,void * ctx)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 *
radius_code_string(int code)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 *
radius_acct_status_type_string(uint32_t type)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
radiusd_conf_init(struct radiusd * conf)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
radiusd_access_response_fixup(struct radius_query * q,struct radius_query * q0,bool islast)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 *
radiusd_find_query(struct radiusd * radiusd,u_int q_id)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
radiusd_imsg_compose_module(struct radiusd * radiusd,const char * module_name,uint32_t type,uint32_t id,pid_t pid,int fd,void * data,size_t datalen)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 *
radiusd_module_load(struct radiusd * radiusd,const char * path,const char * name)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
radiusd_module_start(struct radiusd_module * module)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
radiusd_module_stop(struct radiusd_module * module)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
radiusd_module_close(struct radiusd_module * module)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
radiusd_module_unload(struct radiusd_module * module)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
radiusd_module_on_imsg_io(int fd,short evmask,void * ctx)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
radiusd_module_reset_ev_handler(struct radiusd_module * module)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
radiusd_module_imsg_read(struct radiusd_module * module)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
radiusd_module_imsg(struct radiusd_module * module,struct imsg * imsg)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 *
radiusd_module_recv_radpkt(struct radiusd_module * module,struct imsg * imsg,uint32_t imsg_type,const char * type_str)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
radiusd_module_set(struct radiusd_module * module,const char * name,int argc,char * const * argv)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
radiusd_module_userpass(struct radiusd_module * module,struct radius_query * q)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
radiusd_module_access_request(struct radiusd_module * module,struct radius_query * q)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
radiusd_module_next_response(struct radiusd_module * module,struct radius_query * q,RADIUS_PACKET * pkt)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
radiusd_module_request_decoration(struct radiusd_module * module,struct radius_query * q)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
radiusd_module_response_decoration(struct radiusd_module * module,struct radius_query * q)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
radiusd_module_account_request(struct radiusd_module * module,struct radius_query * q)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
imsg_compose_radius_packet(struct imsgbuf * ibuf,uint32_t type,u_int q_id,RADIUS_PACKET * radpkt)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
close_stdio(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
imsg_event_add(struct imsgev * iev)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
imsg_compose_event(struct imsgev * iev,uint32_t type,uint32_t peerid,pid_t pid,int fd,void * data,size_t datalen)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
imsg_composev_event(struct imsgev * iev,uint32_t type,uint32_t peerid,pid_t pid,int fd,struct iovec * iov,int niov)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