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