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