1 /* $OpenBSD: radiusd.c,v 1.27 2019/06/28 13:32:49 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2013 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 <sys/socket.h> 21 #include <sys/queue.h> 22 #include <sys/uio.h> 23 #include <sys/wait.h> 24 #include <netinet/in.h> 25 26 #include <dlfcn.h> 27 #include <err.h> 28 #include <errno.h> 29 #include <event.h> 30 #include <fcntl.h> 31 #include <fnmatch.h> 32 #include <imsg.h> 33 #include <md5.h> 34 #include <netdb.h> 35 #include <pwd.h> 36 #include <signal.h> 37 #include <stdbool.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <syslog.h> 42 #include <unistd.h> 43 #include <util.h> 44 45 #include <radius.h> 46 47 #include "radiusd.h" 48 #include "radiusd_local.h" 49 #include "log.h" 50 #include "util.h" 51 #include "imsg_subr.h" 52 53 static int radiusd_start(struct radiusd *); 54 static void radiusd_stop(struct radiusd *); 55 static void radiusd_free(struct radiusd *); 56 static void radiusd_listen_on_event(int, short, void *); 57 static void radiusd_on_sigterm(int, short, void *); 58 static void radiusd_on_sigint(int, short, void *); 59 static void radiusd_on_sighup(int, short, void *); 60 static void radiusd_on_sigchld(int, short, void *); 61 static int radius_query_request_decoration(struct radius_query *); 62 static int radius_query_response_decoration( 63 struct radius_query *); 64 static const char *radius_code_string(int); 65 static int radiusd_access_response_fixup (struct radius_query *); 66 67 68 69 static void radiusd_module_reset_ev_handler( 70 struct radiusd_module *); 71 static int radiusd_module_imsg_read(struct radiusd_module *, 72 bool); 73 static void radiusd_module_imsg(struct radiusd_module *, 74 struct imsg *); 75 76 static struct radiusd_module_radpkt_arg * 77 radiusd_module_recv_radpkt(struct radiusd_module *, 78 struct imsg *, uint32_t, const char *); 79 static void radiusd_module_on_imsg_io(int, short, void *); 80 void radiusd_module_start(struct radiusd_module *); 81 void radiusd_module_stop(struct radiusd_module *); 82 static void radiusd_module_close(struct radiusd_module *); 83 static void radiusd_module_userpass(struct radiusd_module *, 84 struct radius_query *); 85 static void radiusd_module_access_request(struct radiusd_module *, 86 struct radius_query *); 87 88 static u_int radius_query_id_seq = 0; 89 int debug = 0; 90 91 static __dead void 92 usage(void) 93 { 94 extern char *__progname; 95 96 fprintf(stderr, "usage: %s [-dn] [-f file]\n", __progname); 97 exit(EXIT_FAILURE); 98 } 99 100 int 101 main(int argc, char *argv[]) 102 { 103 extern char *__progname; 104 const char *conffile = CONFFILE; 105 int ch; 106 struct radiusd *radiusd; 107 bool noaction = false; 108 struct passwd *pw; 109 110 while ((ch = getopt(argc, argv, "df:n")) != -1) 111 switch (ch) { 112 case 'd': 113 debug++; 114 break; 115 116 case 'f': 117 conffile = optarg; 118 break; 119 120 case 'n': 121 noaction = true; 122 break; 123 124 default: 125 usage(); 126 /* NOTREACHED */ 127 } 128 129 argc -= optind; 130 argv += optind; 131 132 if (argc != 0) 133 usage(); 134 135 if ((radiusd = calloc(1, sizeof(*radiusd))) == NULL) 136 err(1, "calloc"); 137 TAILQ_INIT(&radiusd->listen); 138 TAILQ_INIT(&radiusd->query); 139 140 log_init(debug); 141 if (parse_config(conffile, radiusd) != 0) 142 errx(EXIT_FAILURE, "config error"); 143 if (noaction) { 144 fprintf(stderr, "configuration OK\n"); 145 exit(EXIT_SUCCESS); 146 } 147 148 if (debug == 0) 149 daemon(0, 0); 150 event_init(); 151 152 if ((pw = getpwnam(RADIUSD_USER)) == NULL) 153 errx(EXIT_FAILURE, "user `%s' is not found in password " 154 "database", RADIUSD_USER); 155 156 if (chroot(pw->pw_dir) == -1) 157 err(EXIT_FAILURE, "chroot"); 158 if (chdir("/") == -1) 159 err(EXIT_FAILURE, "chdir(\"/\")"); 160 161 if (setgroups(1, &pw->pw_gid) || 162 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 163 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 164 err(EXIT_FAILURE, "cannot drop privileges"); 165 166 signal(SIGPIPE, SIG_IGN); 167 openlog(NULL, LOG_PID, LOG_DAEMON); 168 169 signal_set(&radiusd->ev_sigterm, SIGTERM, radiusd_on_sigterm, radiusd); 170 signal_set(&radiusd->ev_sigint, SIGINT, radiusd_on_sigint, radiusd); 171 signal_set(&radiusd->ev_sighup, SIGHUP, radiusd_on_sighup, radiusd); 172 signal_set(&radiusd->ev_sigchld, SIGCHLD, radiusd_on_sigchld, radiusd); 173 174 if (radiusd_start(radiusd) != 0) 175 errx(EXIT_FAILURE, "start failed"); 176 177 if (pledge("stdio inet", NULL) == -1) 178 err(EXIT_FAILURE, "pledge"); 179 180 if (event_loop(0) < 0) 181 radiusd_stop(radiusd); 182 183 radiusd_free(radiusd); 184 event_base_free(NULL); 185 186 exit(EXIT_SUCCESS); 187 } 188 189 static int 190 radiusd_start(struct radiusd *radiusd) 191 { 192 struct radiusd_listen *l; 193 struct radiusd_module *module; 194 int s; 195 char hbuf[NI_MAXHOST]; 196 197 TAILQ_FOREACH(l, &radiusd->listen, next) { 198 if (getnameinfo( 199 (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len, 200 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) { 201 log_warn("%s: getnameinfo()", __func__); 202 goto on_error; 203 } 204 if ((s = socket(l->addr.ipv4.sin_family, 205 l->stype | SOCK_NONBLOCK, l->sproto)) == -1) { 206 log_warn("Listen %s port %d is failed: socket()", 207 hbuf, (int)htons(l->addr.ipv4.sin_port)); 208 goto on_error; 209 } 210 if (bind(s, (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len) 211 != 0) { 212 log_warn("Listen %s port %d is failed: bind()", 213 hbuf, (int)htons(l->addr.ipv4.sin_port)); 214 close(s); 215 goto on_error; 216 } 217 if (l->addr.ipv4.sin_family == AF_INET) 218 log_info("Start listening on %s:%d/udp", hbuf, 219 (int)ntohs(l->addr.ipv4.sin_port)); 220 else 221 log_info("Start listening on [%s]:%d/udp", hbuf, 222 (int)ntohs(l->addr.ipv4.sin_port)); 223 event_set(&l->ev, s, EV_READ | EV_PERSIST, 224 radiusd_listen_on_event, l); 225 if (event_add(&l->ev, NULL) != 0) { 226 log_warn("event_add() failed at %s()", __func__); 227 close(s); 228 goto on_error; 229 } 230 l->sock = s; 231 l->radiusd = radiusd; 232 } 233 234 signal_add(&radiusd->ev_sigterm, NULL); 235 signal_add(&radiusd->ev_sigint, NULL); 236 signal_add(&radiusd->ev_sighup, NULL); 237 signal_add(&radiusd->ev_sigchld, NULL); 238 239 TAILQ_FOREACH(module, &radiusd->module, next) { 240 if (debug > 0) 241 radiusd_module_set(module, "_debug", 0, NULL); 242 radiusd_module_start(module); 243 } 244 245 return (0); 246 on_error: 247 radiusd_stop(radiusd); 248 249 return (-1); 250 } 251 252 static void 253 radiusd_stop(struct radiusd *radiusd) 254 { 255 char hbuf[NI_MAXHOST]; 256 struct radiusd_listen *l; 257 struct radiusd_module *module; 258 259 TAILQ_FOREACH_REVERSE(l, &radiusd->listen, radiusd_listen_head, next) { 260 if (l->sock >= 0) { 261 if (getnameinfo( 262 (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len, 263 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 264 strlcpy(hbuf, "error", sizeof(hbuf)); 265 if (l->addr.ipv4.sin_family == AF_INET) 266 log_info("Stop listening on %s:%d/udp", hbuf, 267 (int)ntohs(l->addr.ipv4.sin_port)); 268 else 269 log_info("Stop listening on [%s]:%d/udp", hbuf, 270 (int)ntohs(l->addr.ipv4.sin_port)); 271 event_del(&l->ev); 272 close(l->sock); 273 } 274 l->sock = -1; 275 } 276 TAILQ_FOREACH(module, &radiusd->module, next) { 277 radiusd_module_stop(module); 278 radiusd_module_close(module); 279 } 280 if (signal_pending(&radiusd->ev_sigterm, NULL)) 281 signal_del(&radiusd->ev_sigterm); 282 if (signal_pending(&radiusd->ev_sigint, NULL)) 283 signal_del(&radiusd->ev_sigint); 284 if (signal_pending(&radiusd->ev_sighup, NULL)) 285 signal_del(&radiusd->ev_sighup); 286 if (signal_pending(&radiusd->ev_sigchld, NULL)) 287 signal_del(&radiusd->ev_sigchld); 288 } 289 290 static void 291 radiusd_free(struct radiusd *radiusd) 292 { 293 int i; 294 struct radiusd_listen *listn, *listnt; 295 struct radiusd_client *client, *clientt; 296 struct radiusd_module *module, *modulet; 297 struct radiusd_module_ref *modref, *modreft; 298 struct radiusd_authentication *authen, *authent; 299 300 TAILQ_FOREACH_SAFE(authen, &radiusd->authen, next, authent) { 301 TAILQ_REMOVE(&radiusd->authen, authen, next); 302 free(authen->auth); 303 TAILQ_FOREACH_SAFE(modref, &authen->deco, next, modreft) { 304 TAILQ_REMOVE(&authen->deco, modref, next); 305 free(modref); 306 } 307 for (i = 0; authen->username[i] != NULL; i++) 308 free(authen->username[i]); 309 free(authen->username); 310 free(authen); 311 } 312 TAILQ_FOREACH_SAFE(module, &radiusd->module, next, modulet) { 313 TAILQ_REMOVE(&radiusd->module, module, next); 314 radiusd_module_unload(module); 315 } 316 TAILQ_FOREACH_SAFE(client, &radiusd->client, next, clientt) { 317 TAILQ_REMOVE(&radiusd->client, client, next); 318 explicit_bzero(client->secret, sizeof(client->secret)); 319 free(client); 320 } 321 TAILQ_FOREACH_SAFE(listn, &radiusd->listen, next, listnt) { 322 TAILQ_REMOVE(&radiusd->listen, listn, next); 323 free(listn); 324 } 325 free(radiusd); 326 } 327 328 /*********************************************************************** 329 * Network event handlers 330 ***********************************************************************/ 331 #define IPv4_cmp(_in, _addr, _mask) ( \ 332 ((_in)->s_addr & (_mask)->addr.ipv4.s_addr) == \ 333 (_addr)->addr.ipv4.s_addr) 334 #define s6_addr32(_in6) ((uint32_t *)(_in6)->s6_addr) 335 #define IPv6_cmp(_in6, _addr, _mask) ( \ 336 ((s6_addr32(_in6)[3] & (_mask)->addr.addr32[3]) \ 337 == (_addr)->addr.addr32[3]) && \ 338 ((s6_addr32(_in6)[2] & (_mask)->addr.addr32[2]) \ 339 == (_addr)->addr.addr32[2]) && \ 340 ((s6_addr32(_in6)[1] & (_mask)->addr.addr32[1]) \ 341 == (_addr)->addr.addr32[1]) && \ 342 ((s6_addr32(_in6)[0] & (_mask)->addr.addr32[0]) \ 343 == (_addr)->addr.addr32[0])) 344 345 static void 346 radiusd_listen_on_event(int fd, short evmask, void *ctx) 347 { 348 int i, sz, req_id, req_code; 349 struct radiusd_listen *listn = ctx; 350 static u_char buf[65535]; 351 static char username[256]; 352 struct sockaddr_storage peer; 353 socklen_t peersz; 354 RADIUS_PACKET *packet = NULL; 355 char peerstr[NI_MAXHOST + NI_MAXSERV + 30]; 356 struct radiusd_authentication *authen; 357 struct radiusd_client *client; 358 struct radius_query *q; 359 #define in(_x) (((struct sockaddr_in *)_x)->sin_addr) 360 #define in6(_x) (((struct sockaddr_in6 *)_x)->sin6_addr) 361 362 if (evmask & EV_READ) { 363 peersz = sizeof(peer); 364 if ((sz = recvfrom(listn->sock, buf, sizeof(buf), 0, 365 (struct sockaddr *)&peer, &peersz)) == -1) { 366 if (errno == EAGAIN) 367 return; 368 log_warn("%s: recvfrom() failed", __func__); 369 goto on_error; 370 } 371 RADIUSD_ASSERT(peer.ss_family == AF_INET || 372 peer.ss_family == AF_INET6); 373 374 /* prepare some information about this messages */ 375 if (addrport_tostring((struct sockaddr *)&peer, peersz, 376 peerstr, sizeof(peerstr)) == NULL) { 377 log_warn("%s: getnameinfo() failed", __func__); 378 goto on_error; 379 } 380 if ((packet = radius_convert_packet(buf, sz)) == NULL) { 381 log_warn("%s: radius_convert_packet() failed", 382 __func__); 383 goto on_error; 384 } 385 req_id = radius_get_id(packet); 386 req_code = radius_get_code(packet); 387 388 /* 389 * Find a matching `client' entry 390 */ 391 TAILQ_FOREACH(client, &listn->radiusd->client, next) { 392 if (client->af != peer.ss_family) 393 continue; 394 if (peer.ss_family == AF_INET && 395 IPv4_cmp(&((struct sockaddr_in *)&peer)->sin_addr, 396 &client->addr, &client->mask)) 397 break; 398 else if (peer.ss_family == AF_INET6 && 399 IPv6_cmp(&((struct sockaddr_in6 *)&peer)->sin6_addr, 400 &client->addr, &client->mask)) 401 break; 402 } 403 if (client == NULL) { 404 log_warnx("Received %s(code=%d) from %s id=%d: " 405 "no `client' matches", radius_code_string(req_code), 406 req_code, peerstr, req_id); 407 goto on_error; 408 } 409 410 /* Check the client's Message-Authenticator */ 411 if (client->msgauth_required && 412 !radius_has_attr(packet, 413 RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) { 414 log_warnx("Received %s(code=%d) from %s id=%d: " 415 "no message authenticator", 416 radius_code_string(req_code), req_code, peerstr, 417 req_id); 418 goto on_error; 419 } 420 421 if (radius_has_attr(packet, 422 RADIUS_TYPE_MESSAGE_AUTHENTICATOR) && 423 radius_check_message_authenticator(packet, client->secret) 424 != 0) { 425 log_warnx("Received %s(code=%d) from %s id=%d: " 426 "bad message authenticator", 427 radius_code_string(req_code), req_code, peerstr, 428 req_id); 429 goto on_error; 430 } 431 432 /* 433 * Find a duplicate request. In RFC 2865, it has the same 434 * source IP address and source UDP port and Identifier. 435 */ 436 TAILQ_FOREACH(q, &listn->radiusd->query, next) { 437 if (peer.ss_family == q->clientaddr.ss_family && 438 ((peer.ss_family == AF_INET && 439 in(&q->clientaddr).s_addr == 440 in(&peer).s_addr) || 441 (peer.ss_family == AF_INET6 && 442 IN6_ARE_ADDR_EQUAL( 443 &in6(&q->clientaddr), &in6(&peer)))) && 444 ((struct sockaddr_in *)&q->clientaddr)->sin_port == 445 ((struct sockaddr_in *)&peer)->sin_port && 446 req_id == q->req_id) 447 break; /* found it */ 448 } 449 if (q != NULL) { 450 log_info("Received %s(code=%d) from %s id=%d: " 451 "duplicate request by q=%u", 452 radius_code_string(req_code), req_code, peerstr, 453 req_id, q->id); 454 /* XXX RFC 5080 suggests to answer the cached result */ 455 goto on_error; 456 } 457 458 /* FIXME: we can support other request codes */ 459 if (req_code != RADIUS_CODE_ACCESS_REQUEST) { 460 log_info("Received %s(code=%d) from %s id=%d: %s " 461 "is not supported in this implementation", 462 radius_code_string(req_code), req_code, peerstr, 463 req_id, radius_code_string(req_code)); 464 goto on_error; 465 } 466 467 /* 468 * Find a matching `authenticate' entry 469 */ 470 if (radius_get_string_attr(packet, RADIUS_TYPE_USER_NAME, 471 username, sizeof(username)) != 0) { 472 log_info("Received %s(code=%d) from %s id=%d: " 473 "no User-Name attribute", 474 radius_code_string(req_code), req_code, peerstr, 475 req_id); 476 goto on_error; 477 } 478 TAILQ_FOREACH(authen, &listn->radiusd->authen, next) { 479 for (i = 0; authen->username[i] != NULL; i++) { 480 if (fnmatch(authen->username[i], username, 0) 481 == 0) 482 goto found; 483 } 484 } 485 if (authen == NULL) { 486 log_warnx("Received %s(code=%d) from %s id=%d " 487 "username=%s: no `authenticate' matches.", 488 radius_code_string(req_code), req_code, peerstr, 489 req_id, username); 490 goto on_error; 491 } 492 found: 493 if (!MODULE_DO_USERPASS(authen->auth->module) && 494 !MODULE_DO_ACCSREQ(authen->auth->module)) { 495 log_warnx("Received %s(code=%d) from %s id=%d " 496 "username=%s: module `%s' is not running.", 497 radius_code_string(req_code), req_code, peerstr, 498 req_id, username, authen->auth->module->name); 499 goto on_error; 500 } 501 if ((q = calloc(1, sizeof(struct radius_query))) == NULL) { 502 log_warn("%s: Out of memory", __func__); 503 goto on_error; 504 } 505 memcpy(&q->clientaddr, &peer, peersz); 506 strlcpy(q->username, username, sizeof(q->username)); 507 q->id = ++radius_query_id_seq; 508 q->clientaddrlen = peersz; 509 q->authen = authen; 510 q->listen = listn; 511 q->req = packet; 512 q->client = client; 513 q->req_id = req_id; 514 radius_get_authenticator(packet, q->req_auth); 515 516 if (radius_query_request_decoration(q) != 0) { 517 log_warnx( 518 "Received %s(code=%d) from %s id=%d username=%s " 519 "q=%u: failed to decorate the request", 520 radius_code_string(req_code), req_code, peerstr, 521 q->req_id, q->username, q->id); 522 radiusd_access_request_aborted(q); 523 return; 524 } 525 log_info("Received %s(code=%d) from %s id=%d username=%s " 526 "q=%u: `%s' authentication is starting", 527 radius_code_string(req_code), req_code, peerstr, q->req_id, 528 q->username, q->id, q->authen->auth->module->name); 529 TAILQ_INSERT_TAIL(&listn->radiusd->query, q, next); 530 531 if (MODULE_DO_ACCSREQ(authen->auth->module)) { 532 radiusd_module_access_request(authen->auth->module, q); 533 } else if (MODULE_DO_USERPASS(authen->auth->module)) 534 radiusd_module_userpass(authen->auth->module, q); 535 536 return; 537 } 538 on_error: 539 if (packet != NULL) 540 radius_delete_packet(packet); 541 #undef in 542 #undef in6 543 544 return; 545 } 546 547 static int 548 radius_query_request_decoration(struct radius_query *q) 549 { 550 struct radiusd_module_ref *deco; 551 552 TAILQ_FOREACH(deco, &q->authen->deco, next) { 553 /* XXX decoration doesn't work for this moment. */ 554 if (deco->module->request_decoration != NULL && 555 deco->module->request_decoration(NULL, q) != 0) { 556 log_warnx("q=%u request decoration `%s' failed", q->id, 557 deco->module->name); 558 return (-1); 559 } 560 } 561 562 return (0); 563 } 564 565 static int 566 radius_query_response_decoration(struct radius_query *q) 567 { 568 struct radiusd_module_ref *deco; 569 570 TAILQ_FOREACH(deco, &q->authen->deco, next) { 571 /* XXX decoration doesn't work for this moment. */ 572 if (deco->module->response_decoration != NULL && 573 deco->module->response_decoration(NULL, q) != 0) { 574 log_warnx("q=%u response decoration `%s' failed", q->id, 575 deco->module->name); 576 return (-1); 577 } 578 } 579 580 return (0); 581 } 582 583 /*********************************************************************** 584 * Callback functions from the modules 585 ***********************************************************************/ 586 void 587 radiusd_access_request_answer(struct radius_query *q) 588 { 589 int sz, res_id, res_code; 590 char buf[NI_MAXHOST + NI_MAXSERV + 30]; 591 const char *authen_secret = q->authen->auth->module->secret; 592 593 radius_set_request_packet(q->res, q->req); 594 595 if (authen_secret == NULL) { 596 /* 597 * The module couldn't check the autheticators 598 */ 599 if (radius_check_response_authenticator(q->res, 600 q->client->secret) != 0) { 601 log_info("Response from module has bad response " 602 "authenticator: id=%d", q->id); 603 goto on_error; 604 } 605 if (radius_has_attr(q->res, 606 RADIUS_TYPE_MESSAGE_AUTHENTICATOR) && 607 radius_check_message_authenticator(q->res, 608 q->client->secret) != 0) { 609 log_info("Response from module has bad message " 610 "authenticator: id=%d", q->id); 611 goto on_error; 612 } 613 } 614 615 /* Decorate the response */ 616 if (radius_query_response_decoration(q) != 0) 617 goto on_error; 618 619 if (radiusd_access_response_fixup(q) != 0) 620 goto on_error; 621 622 res_id = radius_get_id(q->res); 623 res_code = radius_get_code(q->res); 624 625 /* Reset response/message authenticator */ 626 if (radius_has_attr(q->res, RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) 627 radius_del_attr_all(q->res, RADIUS_TYPE_MESSAGE_AUTHENTICATOR); 628 radius_put_message_authenticator(q->res, q->client->secret); 629 radius_set_response_authenticator(q->res, q->client->secret); 630 631 log_info("Sending %s(code=%d) to %s id=%u q=%u", 632 radius_code_string(res_code), res_code, 633 addrport_tostring((struct sockaddr *)&q->clientaddr, 634 q->clientaddrlen, buf, sizeof(buf)), res_id, q->id); 635 636 if ((sz = sendto(q->listen->sock, radius_get_data(q->res), 637 radius_get_length(q->res), 0, 638 (struct sockaddr *)&q->clientaddr, q->clientaddrlen)) <= 0) 639 log_warn("Sending a RADIUS response failed"); 640 on_error: 641 radiusd_access_request_aborted(q); 642 } 643 644 void 645 radiusd_access_request_aborted(struct radius_query *q) 646 { 647 if (q->req != NULL) 648 radius_delete_packet(q->req); 649 if (q->res != NULL) 650 radius_delete_packet(q->res); 651 TAILQ_REMOVE(&q->listen->radiusd->query, q, next); 652 free(q); 653 } 654 655 /*********************************************************************** 656 * Signal handlers 657 ***********************************************************************/ 658 static void 659 radiusd_on_sigterm(int fd, short evmask, void *ctx) 660 { 661 struct radiusd *radiusd = ctx; 662 663 log_info("Received SIGTERM"); 664 radiusd_stop(radiusd); 665 } 666 667 static void 668 radiusd_on_sigint(int fd, short evmask, void *ctx) 669 { 670 struct radiusd *radiusd = ctx; 671 672 log_info("Received SIGINT"); 673 radiusd_stop(radiusd); 674 } 675 676 static void 677 radiusd_on_sighup(int fd, short evmask, void *ctx) 678 { 679 log_info("Received SIGHUP"); 680 } 681 682 static void 683 radiusd_on_sigchld(int fd, short evmask, void *ctx) 684 { 685 struct radiusd *radiusd = ctx; 686 struct radiusd_module *module; 687 pid_t pid; 688 int status; 689 690 log_debug("Received SIGCHLD"); 691 while ((pid = wait3(&status, WNOHANG, NULL)) != 0) { 692 if (pid == -1) 693 break; 694 TAILQ_FOREACH(module, &radiusd->module, next) { 695 if (module->pid == pid) { 696 if (WIFEXITED(status)) 697 log_warnx("module `%s'(pid=%d) exited " 698 "with status %d", module->name, 699 (int)pid, WEXITSTATUS(status)); 700 else 701 log_warnx("module `%s'(pid=%d) exited " 702 "by signal %d", module->name, 703 (int)pid, WTERMSIG(status)); 704 break; 705 } 706 } 707 if (!module) { 708 if (WIFEXITED(status)) 709 log_warnx("unkown child process pid=%d exited " 710 "with status %d", (int)pid, 711 WEXITSTATUS(status)); 712 else 713 log_warnx("unkown child process pid=%d exited " 714 "by signal %d", (int)pid, 715 WTERMSIG(status)); 716 } 717 } 718 } 719 720 static const char * 721 radius_code_string(int code) 722 { 723 int i; 724 struct _codestrings { 725 int code; 726 const char *string; 727 } codestrings[] = { 728 { RADIUS_CODE_ACCESS_REQUEST, "Access-Request" }, 729 { RADIUS_CODE_ACCESS_ACCEPT, "Access-Accept" }, 730 { RADIUS_CODE_ACCESS_REJECT, "Access-Reject" }, 731 { RADIUS_CODE_ACCOUNTING_REQUEST, "Accounting-Request" }, 732 { RADIUS_CODE_ACCOUNTING_RESPONSE, "Accounting-Response" }, 733 { RADIUS_CODE_ACCESS_CHALLENGE, "Access-Challenge" }, 734 { RADIUS_CODE_STATUS_SERVER, "Status-Server" }, 735 { RADIUS_CODE_STATUS_CLIENT, "Status-Client" }, 736 { -1, NULL } 737 }; 738 739 for (i = 0; codestrings[i].code != -1; i++) 740 if (codestrings[i].code == code) 741 return (codestrings[i].string); 742 743 return ("Unknown"); 744 } 745 746 void 747 radiusd_conf_init(struct radiusd *conf) 748 { 749 750 TAILQ_INIT(&conf->listen); 751 TAILQ_INIT(&conf->module); 752 TAILQ_INIT(&conf->authen); 753 TAILQ_INIT(&conf->client); 754 755 /* 756 * TODO: load the standard modules 757 */ 758 #if 0 759 static struct radiusd_module *radiusd_standard_modules[] = { 760 NULL 761 }; 762 763 u_int i; 764 struct radiusd_module *module; 765 for (i = 0; radiusd_standard_modules[i] != NULL; i++) { 766 module = radiusd_create_module_class( 767 radiusd_standard_modules[i]); 768 TAILQ_INSERT_TAIL(&conf->module, module, next); 769 } 770 #endif 771 772 return; 773 } 774 775 /* 776 * Fix some attributes which depend the secret value. 777 */ 778 static int 779 radiusd_access_response_fixup(struct radius_query *q) 780 { 781 int res_id; 782 size_t attrlen; 783 u_char req_auth[16], attrbuf[256]; 784 const char *authen_secret = q->authen->auth->module->secret; 785 786 radius_get_authenticator(q->req, req_auth); 787 788 if ((authen_secret != NULL && 789 strcmp(authen_secret, q->client->secret) != 0) || 790 timingsafe_bcmp(q->req_auth, req_auth, 16) != 0) { 791 const char *olds = q->client->secret; 792 const char *news = authen_secret; 793 794 /* RFC 2865 Tunnel-Password */ 795 attrlen = sizeof(attrlen); 796 if (radius_get_raw_attr(q->res, RADIUS_TYPE_TUNNEL_PASSWORD, 797 attrbuf, &attrlen) == 0) { 798 radius_attr_unhide(news, req_auth, 799 attrbuf, attrbuf + 3, attrlen - 3); 800 radius_attr_hide(olds, q->req_auth, 801 attrbuf, attrbuf + 3, attrlen - 3); 802 803 radius_del_attr_all(q->res, 804 RADIUS_TYPE_TUNNEL_PASSWORD); 805 radius_put_raw_attr(q->res, 806 RADIUS_TYPE_TUNNEL_PASSWORD, attrbuf, attrlen); 807 } 808 809 /* RFC 2548 Microsoft MPPE-{Send,Recv}-Key */ 810 attrlen = sizeof(attrlen); 811 if (radius_get_vs_raw_attr(q->res, RADIUS_VENDOR_MICROSOFT, 812 RADIUS_VTYPE_MPPE_SEND_KEY, attrbuf, &attrlen) == 0) { 813 814 /* Re-crypt the KEY */ 815 radius_attr_unhide(news, req_auth, 816 attrbuf, attrbuf + 2, attrlen - 2); 817 radius_attr_hide(olds, q->req_auth, 818 attrbuf, attrbuf + 2, attrlen - 2); 819 820 radius_del_vs_attr_all(q->res, RADIUS_VENDOR_MICROSOFT, 821 RADIUS_VTYPE_MPPE_SEND_KEY); 822 radius_put_vs_raw_attr(q->res, RADIUS_VENDOR_MICROSOFT, 823 RADIUS_VTYPE_MPPE_SEND_KEY, attrbuf, attrlen); 824 } 825 attrlen = sizeof(attrlen); 826 if (radius_get_vs_raw_attr(q->res, RADIUS_VENDOR_MICROSOFT, 827 RADIUS_VTYPE_MPPE_RECV_KEY, attrbuf, &attrlen) == 0) { 828 829 /* Re-crypt the KEY */ 830 radius_attr_unhide(news, req_auth, 831 attrbuf, attrbuf + 2, attrlen - 2); 832 radius_attr_hide(olds, q->req_auth, 833 attrbuf, attrbuf + 2, attrlen - 2); 834 835 radius_del_vs_attr_all(q->res, RADIUS_VENDOR_MICROSOFT, 836 RADIUS_VTYPE_MPPE_RECV_KEY); 837 radius_put_vs_raw_attr(q->res, RADIUS_VENDOR_MICROSOFT, 838 RADIUS_VTYPE_MPPE_RECV_KEY, attrbuf, attrlen); 839 } 840 } 841 842 res_id = radius_get_id(q->res); 843 if (res_id != q->req_id) { 844 /* authentication server change the id */ 845 radius_set_id(q->res, q->req_id); 846 } 847 848 return (0); 849 } 850 851 void 852 radius_attr_hide(const char *secret, const char *authenticator, 853 const u_char *salt, u_char *plain, int plainlen) 854 { 855 int i, j; 856 u_char b[16]; 857 MD5_CTX md5ctx; 858 859 i = 0; 860 do { 861 MD5Init(&md5ctx); 862 MD5Update(&md5ctx, secret, strlen(secret)); 863 if (i == 0) { 864 MD5Update(&md5ctx, authenticator, 16); 865 if (salt != NULL) 866 MD5Update(&md5ctx, salt, 2); 867 } else 868 MD5Update(&md5ctx, plain + i - 16, 16); 869 MD5Final(b, &md5ctx); 870 871 for (j = 0; j < 16 && i < plainlen; i++, j++) 872 plain[i] ^= b[j]; 873 } while (i < plainlen); 874 } 875 876 void 877 radius_attr_unhide(const char *secret, const char *authenticator, 878 const u_char *salt, u_char *crypt0, int crypt0len) 879 { 880 int i, j; 881 u_char b[16]; 882 MD5_CTX md5ctx; 883 884 i = 16 * ((crypt0len - 1) / 16); 885 while (i >= 0) { 886 MD5Init(&md5ctx); 887 MD5Update(&md5ctx, secret, strlen(secret)); 888 if (i == 0) { 889 MD5Update(&md5ctx, authenticator, 16); 890 if (salt != NULL) 891 MD5Update(&md5ctx, salt, 2); 892 } else 893 MD5Update(&md5ctx, crypt0 + i - 16, 16); 894 MD5Final(b, &md5ctx); 895 896 for (j = 0; j < 16 && i + j < crypt0len; j++) 897 crypt0[i + j] ^= b[j]; 898 i -= 16; 899 } 900 } 901 902 static struct radius_query * 903 radiusd_find_query(struct radiusd *radiusd, u_int q_id) 904 { 905 struct radius_query *q; 906 907 TAILQ_FOREACH(q, &radiusd->query, next) { 908 if (q->id == q_id) 909 return (q); 910 } 911 return (NULL); 912 } 913 914 /*********************************************************************** 915 * radiusd module handling 916 ***********************************************************************/ 917 struct radiusd_module * 918 radiusd_module_load(struct radiusd *radiusd, const char *path, const char *name) 919 { 920 struct radiusd_module *module = NULL; 921 pid_t pid; 922 int ival, pairsock[] = { -1, -1 }; 923 const char *av[3]; 924 ssize_t n; 925 struct imsg imsg; 926 927 module = calloc(1, sizeof(struct radiusd_module)); 928 if (module == NULL) 929 fatal("Out of memory"); 930 module->radiusd = radiusd; 931 932 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pairsock) == -1) { 933 log_warn("Could not load module `%s'(%s): pipe()", name, path); 934 goto on_error; 935 } 936 937 pid = fork(); 938 if (pid == -1) { 939 log_warn("Could not load module `%s'(%s): fork()", name, path); 940 goto on_error; 941 } 942 if (pid == 0) { 943 setsid(); 944 close(pairsock[0]); 945 av[0] = path; 946 av[1] = name; 947 av[2] = NULL; 948 dup2(pairsock[1], STDIN_FILENO); 949 dup2(pairsock[1], STDOUT_FILENO); 950 close(pairsock[1]); 951 closefrom(STDERR_FILENO + 1); 952 execv(path, (char * const *)av); 953 log_warn("Failed to execute %s", path); 954 _exit(EXIT_FAILURE); 955 } 956 close(pairsock[1]); 957 958 module->fd = pairsock[0]; 959 if ((ival = fcntl(module->fd, F_GETFL)) == -1) { 960 log_warn("Could not load module `%s': fcntl(F_GETFL)", 961 name); 962 goto on_error; 963 } 964 if (fcntl(module->fd, F_SETFL, ival | O_NONBLOCK) == -1) { 965 log_warn("Could not load module `%s': fcntl(F_SETFL,O_NONBLOCK)", 966 name); 967 goto on_error; 968 } 969 strlcpy(module->name, name, sizeof(module->name)); 970 module->pid = pid; 971 imsg_init(&module->ibuf, module->fd); 972 973 if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0 || 974 (n = imsg_get(&module->ibuf, &imsg)) <= 0) { 975 log_warnx("Could not load module `%s': module didn't " 976 "respond", name); 977 goto on_error; 978 } 979 if (imsg.hdr.type != IMSG_RADIUSD_MODULE_LOAD) { 980 imsg_free(&imsg); 981 log_warnx("Could not load module `%s': unknown imsg type=%d", 982 name, imsg.hdr.type); 983 goto on_error; 984 } 985 986 module->capabilities = 987 ((struct radiusd_module_load_arg *)imsg.data)->cap; 988 989 log_debug("Loaded module `%s' successfully. pid=%d", module->name, 990 module->pid); 991 imsg_free(&imsg); 992 993 return (module); 994 995 on_error: 996 free(module); 997 if (pairsock[0] >= 0) 998 close(pairsock[0]); 999 if (pairsock[1] >= 0) 1000 close(pairsock[1]); 1001 1002 return (NULL); 1003 } 1004 1005 void 1006 radiusd_module_start(struct radiusd_module *module) 1007 { 1008 int datalen; 1009 struct imsg imsg; 1010 struct timeval tv = { 0, 0 }; 1011 1012 RADIUSD_ASSERT(module->fd >= 0); 1013 imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_START, 0, 0, -1, 1014 NULL, 0); 1015 imsg_sync_flush(&module->ibuf, MODULE_IO_TIMEOUT); 1016 if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0 || 1017 imsg_get(&module->ibuf, &imsg) <= 0) { 1018 log_warnx("Module `%s' could not start: no response", 1019 module->name); 1020 goto on_fail; 1021 } 1022 1023 datalen = imsg.hdr.len - IMSG_HEADER_SIZE; 1024 if (imsg.hdr.type != IMSG_OK) { 1025 if (imsg.hdr.type == IMSG_NG) { 1026 if (datalen > 0) 1027 log_warnx("Module `%s' could not start: %s", 1028 module->name, (char *)imsg.data); 1029 else 1030 log_warnx("Module `%s' could not start", 1031 module->name); 1032 } else 1033 log_warnx("Module `%s' could not started: module " 1034 "returned unknow message type %d", module->name, 1035 imsg.hdr.type); 1036 goto on_fail; 1037 } 1038 1039 event_set(&module->ev, module->fd, EV_READ, radiusd_module_on_imsg_io, 1040 module); 1041 event_add(&module->ev, &tv); 1042 log_debug("Module `%s' started successfully", module->name); 1043 1044 return; 1045 on_fail: 1046 radiusd_module_close(module); 1047 return; 1048 } 1049 1050 void 1051 radiusd_module_stop(struct radiusd_module *module) 1052 { 1053 module->stopped = true; 1054 1055 if (module->secret != NULL) { 1056 freezero(module->secret, strlen(module->secret)); 1057 module->secret = NULL; 1058 } 1059 1060 if (module->fd >= 0) { 1061 imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_STOP, 0, 0, -1, 1062 NULL, 0); 1063 radiusd_module_reset_ev_handler(module); 1064 } 1065 } 1066 1067 static void 1068 radiusd_module_close(struct radiusd_module *module) 1069 { 1070 if (module->fd >= 0) { 1071 event_del(&module->ev); 1072 imsg_clear(&module->ibuf); 1073 close(module->fd); 1074 module->fd = -1; 1075 } 1076 } 1077 1078 void 1079 radiusd_module_unload(struct radiusd_module *module) 1080 { 1081 free(module->radpkt); 1082 radiusd_module_close(module); 1083 free(module); 1084 } 1085 1086 static void 1087 radiusd_module_on_imsg_io(int fd, short evmask, void *ctx) 1088 { 1089 struct radiusd_module *module = ctx; 1090 int ret; 1091 1092 if (evmask & EV_WRITE) 1093 module->writeready = true; 1094 1095 if (evmask & EV_READ || module->ibuf.r.wpos > IMSG_HEADER_SIZE) { 1096 if (radiusd_module_imsg_read(module, 1097 (evmask & EV_READ)? true : false) == -1) 1098 goto on_error; 1099 } 1100 1101 while (module->writeready && module->ibuf.w.queued) { 1102 ret = msgbuf_write(&module->ibuf.w); 1103 if (ret > 0) 1104 continue; 1105 module->writeready = false; 1106 if (ret == 0 && errno == EAGAIN) 1107 break; 1108 log_warn("Failed to write to module `%s': msgbuf_write()", 1109 module->name); 1110 goto on_error; 1111 } 1112 radiusd_module_reset_ev_handler(module); 1113 1114 return; 1115 on_error: 1116 radiusd_module_close(module); 1117 } 1118 1119 static void 1120 radiusd_module_reset_ev_handler(struct radiusd_module *module) 1121 { 1122 short evmask; 1123 struct timeval *tvp = NULL, tv = { 0, 0 }; 1124 1125 RADIUSD_ASSERT(module->fd >= 0); 1126 event_del(&module->ev); 1127 1128 evmask = EV_READ; 1129 if (module->ibuf.w.queued) { 1130 if (!module->writeready) 1131 evmask |= EV_WRITE; 1132 else 1133 tvp = &tv; /* fire immediately */ 1134 } else if (module->ibuf.r.wpos > IMSG_HEADER_SIZE) 1135 tvp = &tv; /* fire immediately */ 1136 1137 /* module stopped and no event handler is set */ 1138 if (evmask & EV_WRITE && tvp == NULL && module->stopped) { 1139 /* stop requested and no more to write */ 1140 radiusd_module_close(module); 1141 return; 1142 } 1143 1144 event_set(&module->ev, module->fd, evmask, radiusd_module_on_imsg_io, 1145 module); 1146 if (event_add(&module->ev, tvp) == -1) { 1147 log_warn("Could not set event handlers for module `%s': " 1148 "event_add()", module->name); 1149 radiusd_module_close(module); 1150 } 1151 } 1152 1153 static int 1154 radiusd_module_imsg_read(struct radiusd_module *module, bool doread) 1155 { 1156 int n; 1157 struct imsg imsg; 1158 1159 if (doread) { 1160 if ((n = imsg_read(&module->ibuf)) == -1 || n == 0) { 1161 if (n == -1 && errno == EAGAIN) 1162 return (0); 1163 if (n == -1) 1164 log_warn("Receiving a message from module `%s' " 1165 "failed: imsg_read", module->name); 1166 /* else closed */ 1167 radiusd_module_close(module); 1168 return (-1); 1169 } 1170 } 1171 for (;;) { 1172 if ((n = imsg_get(&module->ibuf, &imsg)) == -1) { 1173 log_warn("Receiving a message from module `%s' failed: " 1174 "imsg_get", module->name); 1175 return (-1); 1176 } 1177 if (n == 0) 1178 return (0); 1179 radiusd_module_imsg(module, &imsg); 1180 } 1181 1182 return (0); 1183 } 1184 1185 static void 1186 radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg) 1187 { 1188 int datalen; 1189 struct radius_query *q; 1190 u_int q_id; 1191 1192 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1193 switch (imsg->hdr.type) { 1194 case IMSG_RADIUSD_MODULE_NOTIFY_SECRET: 1195 if (datalen > 0) { 1196 module->secret = strdup(imsg->data); 1197 if (module->secret == NULL) 1198 log_warn("Could not handle NOTIFY_SECRET " 1199 "from `%s'", module->name); 1200 } 1201 break; 1202 case IMSG_RADIUSD_MODULE_USERPASS_OK: 1203 case IMSG_RADIUSD_MODULE_USERPASS_FAIL: 1204 { 1205 char *msg = NULL; 1206 const char *msgtypestr; 1207 1208 msgtypestr = (imsg->hdr.type == IMSG_RADIUSD_MODULE_USERPASS_OK) 1209 ? "USERPASS_OK" : "USERPASS_NG"; 1210 1211 q_id = *(u_int *)imsg->data; 1212 if (datalen > (ssize_t)sizeof(u_int)) 1213 msg = (char *)(((u_int *)imsg->data) + 1); 1214 1215 q = radiusd_find_query(module->radiusd, q_id); 1216 if (q == NULL) { 1217 log_warnx("Received %s from `%s', but query id=%u " 1218 "unknown", msgtypestr, module->name, q_id); 1219 break; 1220 } 1221 1222 if ((q->res = radius_new_response_packet( 1223 (imsg->hdr.type == IMSG_RADIUSD_MODULE_USERPASS_OK) 1224 ? RADIUS_CODE_ACCESS_ACCEPT : RADIUS_CODE_ACCESS_REJECT, 1225 q->req)) == NULL) { 1226 log_warn("radius_new_response_packet() failed"); 1227 radiusd_access_request_aborted(q); 1228 } else { 1229 if (msg) 1230 radius_put_string_attr(q->res, 1231 RADIUS_TYPE_REPLY_MESSAGE, msg); 1232 radius_set_response_authenticator(q->res, 1233 q->client->secret); 1234 radiusd_access_request_answer(q); 1235 } 1236 break; 1237 } 1238 case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER: 1239 { 1240 static struct radiusd_module_radpkt_arg *ans; 1241 if (datalen < 1242 (ssize_t)sizeof(struct radiusd_module_radpkt_arg)) { 1243 log_warnx("Received ACCSREQ_ANSWER message, but " 1244 "length is wrong"); 1245 break; 1246 } 1247 q_id = ((struct radiusd_module_radpkt_arg *)imsg->data)->q_id; 1248 q = radiusd_find_query(module->radiusd, q_id); 1249 if (q == NULL) { 1250 log_warnx("Received ACCSREQ_ANSWER from %s, but query " 1251 "id=%u unknown", module->name, q_id); 1252 break; 1253 } 1254 if ((ans = radiusd_module_recv_radpkt(module, imsg, 1255 IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER, 1256 "ACCSREQ_ANSWER")) != NULL) { 1257 q->res = radius_convert_packet( 1258 module->radpkt, module->radpktoff); 1259 radiusd_access_request_answer(q); 1260 module->radpktoff = 0; 1261 } 1262 break; 1263 } 1264 case IMSG_RADIUSD_MODULE_ACCSREQ_ABORTED: 1265 { 1266 q_id = *((u_int *)imsg->data); 1267 q = radiusd_find_query(module->radiusd, q_id); 1268 if (q == NULL) { 1269 log_warnx("Received ACCSREQ_ABORT from %s, but query " 1270 "id=%u unknown", module->name, q_id); 1271 break; 1272 } 1273 radiusd_access_request_aborted(q); 1274 break; 1275 } 1276 default: 1277 RADIUSD_DBG(("Unhandled imsg type=%d", 1278 imsg->hdr.type)); 1279 } 1280 } 1281 1282 static struct radiusd_module_radpkt_arg * 1283 radiusd_module_recv_radpkt(struct radiusd_module *module, struct imsg *imsg, 1284 uint32_t imsg_type, const char *type_str) 1285 { 1286 struct radiusd_module_radpkt_arg *ans; 1287 int datalen, chunklen; 1288 1289 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 1290 ans = (struct radiusd_module_radpkt_arg *)imsg->data; 1291 if (module->radpktsiz < ans->pktlen) { 1292 u_char *nradpkt; 1293 if ((nradpkt = realloc(module->radpkt, ans->pktlen)) == NULL) { 1294 log_warn("Could not handle received %s message from " 1295 "`%s'", type_str, module->name); 1296 goto on_fail; 1297 } 1298 module->radpkt = nradpkt; 1299 module->radpktsiz = ans->pktlen; 1300 } 1301 chunklen = datalen - sizeof(struct radiusd_module_radpkt_arg); 1302 if (chunklen > module->radpktsiz - module->radpktoff) { 1303 log_warnx("Could not handle received %s message from `%s': " 1304 "received length is too big", type_str, module->name); 1305 goto on_fail; 1306 } 1307 memcpy(module->radpkt + module->radpktoff, 1308 (caddr_t)(ans + 1), chunklen); 1309 module->radpktoff += chunklen; 1310 if (!ans->final) 1311 return (NULL); /* again */ 1312 if (module->radpktoff != ans->pktlen) { 1313 log_warnx("Could not handle received %s message from `%s': " 1314 "length is mismatch", type_str, module->name); 1315 goto on_fail; 1316 } 1317 1318 return (ans); 1319 on_fail: 1320 module->radpktoff = 0; 1321 return (NULL); 1322 } 1323 1324 int 1325 radiusd_module_set(struct radiusd_module *module, const char *name, 1326 int argc, char * const * argv) 1327 { 1328 struct radiusd_module_set_arg arg; 1329 struct radiusd_module_object *val; 1330 int i, niov = 0; 1331 u_char *buf = NULL, *buf0; 1332 ssize_t n; 1333 size_t bufsiz = 0, bufoff = 0, bufsiz0; 1334 size_t vallen, valsiz; 1335 struct iovec iov[2]; 1336 struct imsg imsg; 1337 1338 memset(&arg, 0, sizeof(arg)); 1339 arg.nparamval = argc; 1340 strlcpy(arg.paramname, name, sizeof(arg.paramname)); 1341 1342 iov[niov].iov_base = &arg; 1343 iov[niov].iov_len = sizeof(struct radiusd_module_set_arg); 1344 niov++; 1345 1346 for (i = 0; i < argc; i++) { 1347 vallen = strlen(argv[i]) + 1; 1348 valsiz = sizeof(struct radiusd_module_object) + vallen; 1349 if (bufsiz < bufoff + valsiz) { 1350 bufsiz0 = bufoff + valsiz + 128; 1351 if ((buf0 = realloc(buf, bufsiz0)) == NULL) { 1352 log_warn("Failed to set config parameter to " 1353 "module `%s': realloc", module->name); 1354 goto on_error; 1355 } 1356 buf = buf0; 1357 bufsiz = bufsiz0; 1358 memset(buf + bufoff, 0, bufsiz - bufoff); 1359 } 1360 val = (struct radiusd_module_object *)(buf + bufoff); 1361 val->size = valsiz; 1362 memcpy(val + 1, argv[i], vallen); 1363 1364 bufoff += valsiz; 1365 } 1366 iov[niov].iov_base = buf; 1367 iov[niov].iov_len = bufoff; 1368 niov++; 1369 1370 if (imsg_composev(&module->ibuf, IMSG_RADIUSD_MODULE_SET_CONFIG, 0, 0, 1371 -1, iov, niov) == -1) { 1372 log_warn("Failed to set config parameter to module `%s': " 1373 "imsg_composev", module->name); 1374 goto on_error; 1375 } 1376 if (imsg_sync_flush(&module->ibuf, MODULE_IO_TIMEOUT) == -1) { 1377 log_warn("Failed to set config parameter to module `%s': " 1378 "imsg_flush_timeout", module->name); 1379 goto on_error; 1380 } 1381 for (;;) { 1382 if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT) <= 0) { 1383 log_warn("Failed to get reply from module `%s': " 1384 "imsg_sync_read", module->name); 1385 goto on_error; 1386 } 1387 if ((n = imsg_get(&module->ibuf, &imsg)) > 0) 1388 break; 1389 if (n < 0) { 1390 log_warn("Failed to get reply from module `%s': " 1391 "imsg_get", module->name); 1392 goto on_error; 1393 } 1394 } 1395 if (imsg.hdr.type == IMSG_NG) { 1396 log_warnx("Could not set `%s' for module `%s': %s", name, 1397 module->name, (char *)imsg.data); 1398 goto on_error; 1399 } else if (imsg.hdr.type != IMSG_OK) { 1400 imsg_free(&imsg); 1401 log_warnx("Failed to get reply from module `%s': " 1402 "unknown imsg type=%d", module->name, imsg.hdr.type); 1403 goto on_error; 1404 } 1405 imsg_free(&imsg); 1406 1407 free(buf); 1408 return (0); 1409 1410 on_error: 1411 free(buf); 1412 return (-1); 1413 } 1414 1415 static void 1416 radiusd_module_userpass(struct radiusd_module *module, struct radius_query *q) 1417 { 1418 struct radiusd_module_userpass_arg userpass; 1419 1420 memset(&userpass, 0, sizeof(userpass)); 1421 userpass.q_id = q->id; 1422 1423 if (radius_get_user_password_attr(q->req, userpass.pass, 1424 sizeof(userpass.pass), q->client->secret) == 0) 1425 userpass.has_pass = true; 1426 else 1427 userpass.has_pass = false; 1428 1429 if (strlcpy(userpass.user, q->username, sizeof(userpass.user)) 1430 >= sizeof(userpass.user)) { 1431 log_warnx("Could request USERPASS to module `%s': " 1432 "User-Name too long", module->name); 1433 goto on_error; 1434 } 1435 imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_USERPASS, 0, 0, -1, 1436 &userpass, sizeof(userpass)); 1437 radiusd_module_reset_ev_handler(module); 1438 return; 1439 on_error: 1440 radiusd_access_request_aborted(q); 1441 } 1442 1443 static void 1444 radiusd_module_access_request(struct radiusd_module *module, 1445 struct radius_query *q) 1446 { 1447 struct radiusd_module_radpkt_arg accsreq; 1448 struct iovec iov[2]; 1449 int off = 0, len, siz; 1450 const u_char *pkt; 1451 RADIUS_PACKET *radpkt; 1452 char pass[256]; 1453 1454 if ((radpkt = radius_convert_packet(radius_get_data(q->req), 1455 radius_get_length(q->req))) == NULL) { 1456 log_warn("Could not send ACCSREQ for `%s'", module->name); 1457 return; 1458 } 1459 if (q->client->secret[0] != '\0' && module->secret != NULL && 1460 radius_get_user_password_attr(radpkt, pass, sizeof(pass), 1461 q->client->secret) == 0) { 1462 radius_del_attr_all(radpkt, RADIUS_TYPE_USER_PASSWORD); 1463 (void)radius_put_raw_attr(radpkt, RADIUS_TYPE_USER_PASSWORD, 1464 pass, strlen(pass)); 1465 } 1466 1467 pkt = radius_get_data(radpkt); 1468 len = radius_get_length(radpkt); 1469 memset(&accsreq, 0, sizeof(accsreq)); 1470 accsreq.q_id = q->id; 1471 accsreq.pktlen = len; 1472 while (off < len) { 1473 siz = MAX_IMSGSIZE - sizeof(accsreq); 1474 if (len - off > siz) 1475 accsreq.final = false; 1476 else { 1477 accsreq.final = true; 1478 siz = len - off; 1479 } 1480 iov[0].iov_base = &accsreq; 1481 iov[0].iov_len = sizeof(accsreq); 1482 iov[1].iov_base = (caddr_t)pkt + off; 1483 iov[1].iov_len = siz; 1484 imsg_composev(&module->ibuf, IMSG_RADIUSD_MODULE_ACCSREQ, 0, 0, 1485 -1, iov, 2); 1486 off += siz; 1487 } 1488 radiusd_module_reset_ev_handler(module); 1489 radius_delete_packet(radpkt); 1490 1491 return; 1492 } 1493