1 /* $OpenBSD: radiusd_ipcp.c,v 1.23 2025/01/29 10:16:05 yasuoka Exp $ */ 2 3 /* 4 * Copyright (c) 2024 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/queue.h> 21 #include <sys/socket.h> 22 #include <sys/time.h> 23 #include <sys/tree.h> 24 #include <arpa/inet.h> 25 26 #include <inttypes.h> 27 #include <netdb.h> 28 #include <db.h> 29 #include <err.h> 30 #include <errno.h> 31 #include <event.h> 32 #include <fcntl.h> 33 #include <pwd.h> 34 #include <radius.h> 35 #include <stdbool.h> 36 #include <stddef.h> 37 #include <stdint.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <time.h> 42 #include <unistd.h> 43 #include <imsg.h> 44 45 #include "radiusd.h" 46 #include "radiusd_module.h" 47 #include "radiusd_ipcp.h" 48 #include "log.h" 49 50 #define RADIUSD_IPCP_START_WAIT 60 51 52 enum ipcp_address_type { 53 ADDRESS_TYPE_POOL, 54 ADDRESS_TYPE_STATIC 55 }; 56 57 struct ipcp_address { 58 enum ipcp_address_type type; 59 struct in_addr start; 60 struct in_addr end; 61 int naddrs; 62 TAILQ_ENTRY(ipcp_address) next; 63 }; 64 65 struct user { 66 TAILQ_HEAD(, assigned_ipv4) ipv4s; 67 RB_ENTRY(user) tree; 68 char name[0]; 69 }; 70 71 struct radiusctl_client { 72 int peerid; 73 TAILQ_ENTRY(radiusctl_client) entry; 74 }; 75 76 struct module_ipcp_dae; 77 78 struct assigned_ipv4 { 79 struct in_addr ipv4; 80 unsigned seq; 81 char session_id[256]; 82 char auth_method[16]; 83 struct user *user; 84 uint32_t session_timeout; 85 struct timespec start; 86 struct timespec timeout; 87 struct in_addr nas_ipv4; 88 struct in6_addr nas_ipv6; 89 char nas_id[256]; 90 const char *tun_type; 91 union { 92 struct sockaddr_in sin4; 93 struct sockaddr_in6 sin6; 94 } tun_client; 95 96 struct timespec authtime; 97 RB_ENTRY(assigned_ipv4) tree; 98 TAILQ_ENTRY(assigned_ipv4) next; 99 100 /* RFC 5176 Dynamic Authorization Extensions for RADIUS */ 101 struct module_ipcp_dae *dae; 102 RADIUS_PACKET *dae_reqpkt; 103 TAILQ_ENTRY(assigned_ipv4) dae_next; 104 int dae_ntry; 105 struct event dae_evtimer; 106 TAILQ_HEAD(, radiusctl_client) dae_clients; 107 }; 108 109 struct module_ipcp_ctrlconn { 110 uint32_t peerid; 111 TAILQ_ENTRY(module_ipcp_ctrlconn) 112 next; 113 }; 114 115 struct module_ipcp_dae { 116 struct module_ipcp *ipcp; 117 int sock; 118 char nas_id[256]; 119 char secret[80]; 120 union { 121 struct sockaddr_in sin4; 122 struct sockaddr_in6 sin6; 123 } nas_addr; 124 struct event ev_sock; 125 struct event ev_reqs; 126 TAILQ_ENTRY(module_ipcp_dae) next; 127 TAILQ_HEAD(, assigned_ipv4) reqs; 128 int ninflight; 129 }; 130 131 struct module_ipcp { 132 struct module_base *base; 133 int nsessions; 134 unsigned seq; 135 int max_sessions; 136 int user_max_sessions; 137 int start_wait; 138 int session_timeout; 139 bool no_session_timeout; 140 struct timespec uptime; 141 struct in_addr name_server[2]; 142 struct in_addr netbios_server[2]; 143 RB_HEAD(assigned_ipv4_tree, assigned_ipv4) 144 ipv4s; 145 RB_HEAD(user_tree, user) users; 146 int npools; 147 TAILQ_HEAD(,ipcp_address) addrs; 148 TAILQ_HEAD(,module_ipcp_ctrlconn) 149 ctrls; 150 TAILQ_HEAD(,module_ipcp_dae) daes; 151 struct event ev_timer; 152 }; 153 154 #ifndef nitems 155 #define nitems(_x) (sizeof((_x)) / sizeof((_x)[0])) 156 #endif 157 158 #ifndef MAXIMUM 159 #define MAXIMUM(_a, _b) (((_a) > (_b))? (_a) : (_b)) 160 #endif 161 162 static void ipcp_init(struct module_ipcp *); 163 static void ipcp_start(void *); 164 static void ipcp_stop(void *); 165 static void ipcp_fini(struct module_ipcp *); 166 static void ipcp_config_set(void *, const char *, int, char * const *); 167 static void ipcp_dispatch_control(void *, struct imsg *); 168 static int ipcp_notice_startstop(struct module_ipcp *, 169 struct assigned_ipv4 *, int, 170 struct radiusd_ipcp_statistics *); 171 static void ipcp_resdeco(void *, u_int, const u_char *, size_t reqlen, 172 const u_char *, size_t reslen); 173 static void ipcp_reject(struct module_ipcp *, RADIUS_PACKET *, 174 unsigned int, RADIUS_PACKET *, int); 175 static void ipcp_accounting_request(void *, u_int, const u_char *, 176 size_t); 177 178 struct assigned_ipv4 179 *ipcp_ipv4_assign(struct module_ipcp *, struct user *, 180 struct in_addr); 181 static struct assigned_ipv4 182 *ipcp_ipv4_find(struct module_ipcp *, struct in_addr); 183 static void ipcp_ipv4_delete(struct module_ipcp *, 184 struct assigned_ipv4 *, const char *); 185 static void ipcp_ipv4_release(struct module_ipcp *, 186 struct assigned_ipv4 *); 187 static int assigned_ipv4_compar(struct assigned_ipv4 *, 188 struct assigned_ipv4 *); 189 static struct user 190 *ipcp_user_get(struct module_ipcp *, const char *); 191 static int user_compar(struct user *, struct user *); 192 static int ipcp_prepare_db(void); 193 static int ipcp_restore_from_db(struct module_ipcp *); 194 static void ipcp_put_db(struct module_ipcp *, struct assigned_ipv4 *); 195 static void ipcp_del_db(struct module_ipcp *, struct assigned_ipv4 *); 196 static void ipcp_db_dump_fill_record(struct radiusd_ipcp_db_dump *, int, 197 struct assigned_ipv4 *); 198 static void ipcp_update_time(struct module_ipcp *); 199 static void ipcp_on_timer(int, short, void *); 200 static void ipcp_schedule_timer(struct module_ipcp *); 201 static void ipcp_dae_send_disconnect_request(struct assigned_ipv4 *); 202 static void ipcp_dae_request_on_timeout(int, short, void *); 203 static void ipcp_dae_on_event(int, short, void *); 204 static void ipcp_dae_reset_request(struct assigned_ipv4 *); 205 static void ipcp_dae_send_pending_requests(int, short, void *); 206 static struct ipcp_address 207 *parse_address_range(const char *); 208 static const char 209 *radius_tunnel_type_string(unsigned, const char *); 210 static const char 211 *radius_terminate_cause_string(unsigned); 212 static const char 213 *radius_error_cause_string(unsigned); 214 static int parse_addr(const char *, int, struct sockaddr *, socklen_t); 215 static const char 216 *print_addr(struct sockaddr *, char *, size_t); 217 218 RB_PROTOTYPE_STATIC(assigned_ipv4_tree, assigned_ipv4, tree, 219 assigned_ipv4_compar); 220 RB_PROTOTYPE_STATIC(user_tree, user, tree, user_compar); 221 222 int 223 main(int argc, char *argv[]) 224 { 225 struct module_ipcp module_ipcp; 226 struct module_handlers handlers = { 227 .start = ipcp_start, 228 .stop = ipcp_stop, 229 .config_set = ipcp_config_set, 230 .response_decoration = ipcp_resdeco, 231 .accounting_request = ipcp_accounting_request, 232 .dispatch_control = ipcp_dispatch_control 233 }; 234 235 ipcp_init(&module_ipcp); 236 237 if ((module_ipcp.base = module_create(STDIN_FILENO, &module_ipcp, 238 &handlers)) == NULL) 239 err(1, "Could not create a module instance"); 240 241 if (ipcp_prepare_db() == -1) 242 err(1, "ipcp_prepare_db"); 243 244 module_drop_privilege(module_ipcp.base, 1); 245 if (unveil(_PATH_RADIUSD_IPCP_DB, "rw") == -1) 246 err(1, "unveil"); 247 if (pledge("stdio inet rpath wpath flock", NULL) == -1) 248 err(1, "pledge"); 249 setproctitle("[main]"); 250 251 module_load(module_ipcp.base); 252 log_init(0); 253 event_init(); 254 255 module_start(module_ipcp.base); 256 event_loop(0); 257 258 ipcp_fini(&module_ipcp); 259 260 event_loop(0); 261 event_base_free(NULL); 262 263 exit(EXIT_SUCCESS); 264 } 265 266 void 267 ipcp_init(struct module_ipcp *self) 268 { 269 memset(self, 0, sizeof(struct module_ipcp)); 270 TAILQ_INIT(&self->addrs); 271 RB_INIT(&self->ipv4s); 272 RB_INIT(&self->users); 273 TAILQ_INIT(&self->ctrls); 274 TAILQ_INIT(&self->daes); 275 self->seq = 1; 276 self->no_session_timeout = true; 277 ipcp_update_time(self); 278 } 279 280 void 281 ipcp_start(void *ctx) 282 { 283 struct module_ipcp *self = ctx; 284 struct ipcp_address *addr; 285 struct module_ipcp_dae *dae; 286 int sock; 287 288 ipcp_update_time(self); 289 if (self->start_wait == 0) 290 self->start_wait = RADIUSD_IPCP_START_WAIT; 291 292 /* count pool address*/ 293 TAILQ_FOREACH(addr, &self->addrs, next) { 294 if (addr->type == ADDRESS_TYPE_POOL) 295 self->npools += addr->naddrs; 296 } 297 log_info("number of pooled IP addresses = %d", self->npools); 298 299 if (ipcp_restore_from_db(self) == -1) { 300 module_send_message(self->base, IMSG_NG, 301 "Restoring the database failed: %s", strerror(errno)); 302 module_stop(self->base); 303 return; 304 } 305 ipcp_schedule_timer(self); 306 307 /* prepare socket for DAE */ 308 TAILQ_FOREACH(dae, &self->daes, next) { 309 if ((sock = socket(dae->nas_addr.sin4.sin_family, 310 SOCK_DGRAM, IPPROTO_UDP)) == -1) { 311 log_warn("%s: could not start dae: socket()", __func__); 312 return; 313 } 314 if (connect(sock, (struct sockaddr *)&dae->nas_addr, 315 dae->nas_addr.sin4.sin_len) == -1) { 316 log_warn("%s: could not start dae: connect()", 317 __func__); 318 return; 319 } 320 dae->sock = sock; 321 event_set(&dae->ev_sock, sock, EV_READ | EV_PERSIST, 322 ipcp_dae_on_event, dae); 323 event_add(&dae->ev_sock, NULL); 324 evtimer_set(&dae->ev_reqs, ipcp_dae_send_pending_requests, dae); 325 } 326 327 module_send_message(self->base, IMSG_OK, NULL); 328 } 329 330 void 331 ipcp_stop(void *ctx) 332 { 333 struct module_ipcp *self = ctx; 334 struct module_ipcp_dae *dae; 335 336 ipcp_update_time(self); 337 /* stop the sockets for DAE */ 338 TAILQ_FOREACH(dae, &self->daes, next) { 339 if (dae->sock >= 0) { 340 event_del(&dae->ev_sock); 341 close(dae->sock); 342 dae->sock = -1; 343 } 344 if (evtimer_pending(&dae->ev_reqs, NULL)) 345 event_del(&dae->ev_reqs); 346 } 347 if (evtimer_pending(&self->ev_timer, NULL)) 348 evtimer_del(&self->ev_timer); 349 } 350 351 void 352 ipcp_fini(struct module_ipcp *self) 353 { 354 struct assigned_ipv4 *assign, *assignt; 355 struct user *user, *usert; 356 struct module_ipcp_ctrlconn *ctrl, *ctrlt; 357 struct module_ipcp_dae *dae, *daet; 358 struct ipcp_address *addr, *addrt; 359 360 RB_FOREACH_SAFE(assign, assigned_ipv4_tree, &self->ipv4s, assignt) 361 ipcp_ipv4_release(self, assign); 362 RB_FOREACH_SAFE(user, user_tree, &self->users, usert) { 363 RB_REMOVE(user_tree, &self->users, user); 364 free(user); 365 } 366 TAILQ_FOREACH_SAFE(ctrl, &self->ctrls, next, ctrlt) 367 free(ctrl); 368 TAILQ_FOREACH_SAFE(dae, &self->daes, next, daet) { 369 if (dae->sock >= 0) { 370 event_del(&dae->ev_sock); 371 close(dae->sock); 372 } 373 free(dae); 374 } 375 TAILQ_FOREACH_SAFE(addr, &self->addrs, next, addrt) 376 free(addr); 377 if (evtimer_pending(&self->ev_timer, NULL)) 378 evtimer_del(&self->ev_timer); 379 module_destroy(self->base); 380 } 381 382 void 383 ipcp_config_set(void *ctx, const char *name, int argc, char * const * argv) 384 { 385 struct module_ipcp *module = ctx; 386 const char *errmsg = "none"; 387 int i; 388 struct ipcp_address *addr; 389 struct in_addr ina; 390 struct module_ipcp_dae dae, *dae0; 391 392 if (strcmp(name, "address") == 0) { 393 SYNTAX_ASSERT(argc >= 1, 394 "specify one of pool, server, nas-select, or user-select"); 395 if (strcmp(argv[0], "pool") == 0) { 396 SYNTAX_ASSERT(argc >= 2, 397 "`address pool' must have one address range at " 398 "least"); 399 addr = TAILQ_FIRST(&module->addrs); 400 for (i = 0; i < argc - 1; i++) { 401 if ((addr = parse_address_range(argv[i + 1])) 402 == NULL) { 403 module_send_message(module->base, 404 IMSG_NG, "Invalid address range: " 405 "%s", argv[i + 1]); 406 return; 407 } 408 addr->type = ADDRESS_TYPE_POOL; 409 TAILQ_INSERT_TAIL(&module->addrs, addr, next); 410 } 411 } else if (strcmp(argv[0], "static") == 0) { 412 SYNTAX_ASSERT(argc >= 2, 413 "`address static' must have one address range at " 414 "least"); 415 addr = TAILQ_FIRST(&module->addrs); 416 for (i = 0; i < argc - 1; i++) { 417 if ((addr = parse_address_range(argv[i + 1])) 418 == NULL) { 419 module_send_message(module->base, 420 IMSG_NG, "Invalid address range: " 421 "%s", argv[i + 1]); 422 return; 423 } 424 addr->type = ADDRESS_TYPE_STATIC; 425 TAILQ_INSERT_TAIL(&module->addrs, addr, next); 426 } 427 } else 428 SYNTAX_ASSERT(0, "specify pool or static"); 429 } else if (strcmp(name, "max-sessions") == 0) { 430 SYNTAX_ASSERT(argc == 1, 431 "`max-sessions' must have an argument"); 432 module->max_sessions = strtonum(argv[0], 0, INT_MAX, &errmsg); 433 if (errmsg != NULL) { 434 module_send_message(module->base, IMSG_NG, 435 "could not parse `max-sessions': %s", errmsg); 436 return; 437 } 438 } else if (strcmp(name, "user-max-sessions") == 0) { 439 SYNTAX_ASSERT(argc == 1, "`max-session' must have an argument"); 440 module->user_max_sessions = strtonum(argv[0], 0, INT_MAX, 441 &errmsg); 442 if (errmsg != NULL) { 443 module_send_message(module->base, IMSG_NG, 444 "could not parse `user-max-session': %s", errmsg); 445 return; 446 } 447 } else if (strcmp(name, "start-wait") == 0) { 448 SYNTAX_ASSERT(argc == 1, "`start-wait' must have an argument"); 449 module->start_wait = strtonum(argv[0], 1, INT_MAX, &errmsg); 450 if (errmsg != NULL) { 451 module_send_message(module->base, IMSG_NG, 452 "could not parse `start-wait': %s", errmsg); 453 return; 454 } 455 } else if (strcmp(name, "name-server") == 0) { 456 SYNTAX_ASSERT(argc == 1 || argc == 2, 457 "specify 1 or 2 addresses for `name-server'"); 458 for (i = 0; i < argc; i++) { 459 if (inet_pton(AF_INET, argv[i], &ina) != 1) { 460 module_send_message(module->base, IMSG_NG, 461 "Invalid IP address: %s", argv[i]); 462 return; 463 } 464 if (module->name_server[0].s_addr == 0) 465 module->name_server[0] = ina; 466 else if (module->name_server[1].s_addr == 0) 467 module->name_server[1] = ina; 468 else 469 SYNTAX_ASSERT(0, 470 "too many `name-server' is configured"); 471 } 472 } else if (strcmp(name, "netbios-server") == 0) { 473 SYNTAX_ASSERT(argc == 1 || argc == 2, 474 "specify 1 or 2 addresses for `name-server'"); 475 for (i = 0; i < argc; i++) { 476 if (inet_pton(AF_INET, argv[i], &ina) != 1) { 477 module_send_message(module->base, IMSG_NG, 478 "Invalid IP address: %s", argv[i]); 479 return; 480 } 481 if (module->netbios_server[0].s_addr == 0) 482 module->netbios_server[0] = ina; 483 else if (module->netbios_server[1].s_addr == 0) 484 module->netbios_server[1] = ina; 485 else 486 SYNTAX_ASSERT(0, 487 "too many `name-server' is configured"); 488 } 489 } else if (strcmp(name, "session-timeout") == 0) { 490 SYNTAX_ASSERT(argc == 1, 491 "`session-timeout' must have an argument"); 492 if (strcmp(argv[0], "radius") == 0) { 493 module->no_session_timeout = false; 494 module->session_timeout = 0; 495 } else { 496 module->no_session_timeout = false; 497 module->session_timeout = strtonum(argv[0], 1, INT_MAX, 498 &errmsg); 499 if (errmsg != NULL) { 500 module_send_message(module->base, IMSG_NG, 501 "could not parse `session-timeout': %s", 502 errmsg); 503 return; 504 } 505 } 506 } else if (strcmp(name, "dae") == 0) { 507 memset(&dae, 0, sizeof(dae)); 508 dae.sock = -1; 509 if (!(argc >= 1 || strcmp(argv[1], "server") == 0)) { 510 module_send_message(module->base, IMSG_NG, 511 "`%s' is unknown", argv[1]); 512 return; 513 } 514 i = 1; 515 SYNTAX_ASSERT(i < argc, "no address[:port] for dae server"); 516 if (i < argc && 517 parse_addr(argv[i], AF_UNSPEC, (struct sockaddr *) 518 &dae.nas_addr, sizeof(dae.nas_addr)) == -1) { 519 module_send_message(module->base, IMSG_NG, 520 "failed to parse dae server's address, %s", 521 argv[i]); 522 return; 523 } 524 if (ntohs(dae.nas_addr.sin4.sin_port) == 0) 525 dae.nas_addr.sin4.sin_port = 526 htons(RADIUS_DAE_DEFAULT_PORT); 527 i++; 528 SYNTAX_ASSERT(i < argc, "no secret for dae server"); 529 if (strlcpy(dae.secret, argv[i++], sizeof(dae.secret)) >= 530 sizeof(dae.secret)) { 531 module_send_message(module->base, IMSG_NG, 532 "dae server's secret must be < %d bytes", 533 (int)sizeof(dae.secret) - 1); 534 return; 535 } 536 if (i < argc) 537 strlcpy(dae.nas_id, argv[i++], sizeof(dae.nas_id)); 538 if ((dae0 = calloc(1, sizeof(struct module_ipcp_dae))) == NULL) 539 { 540 module_send_message(module->base, IMSG_NG, 541 "%s", strerror(errno)); 542 return; 543 } 544 *dae0 = dae; 545 TAILQ_INIT(&dae0->reqs); 546 TAILQ_INSERT_TAIL(&module->daes, dae0, next); 547 dae0->ipcp = module; 548 } else if (strcmp(name, "_debug") == 0) 549 log_init(1); 550 else if (strncmp(name, "_", 1) == 0) 551 /* ignore */; 552 else { 553 module_send_message(module->base, IMSG_NG, 554 "Unknown config parameter name `%s'", name); 555 return; 556 } 557 module_send_message(module->base, IMSG_OK, NULL); 558 559 return; 560 syntax_error: 561 module_send_message(module->base, IMSG_NG, "%s", errmsg); 562 } 563 564 void 565 ipcp_dispatch_control(void *ctx, struct imsg *imsg) 566 { 567 struct module_ipcp *self = ctx; 568 struct assigned_ipv4 *assign; 569 struct radiusd_ipcp_db_dump *dump; 570 struct module_ipcp_ctrlconn *ctrl, *ctrlt; 571 int i; 572 size_t dumpsiz; 573 u_int datalen; 574 unsigned seq; 575 struct radiusctl_client *client; 576 const char *cause; 577 578 ipcp_update_time(self); 579 datalen = imsg->hdr.len - IMSG_HEADER_SIZE; 580 switch (imsg->hdr.type) { 581 case IMSG_RADIUSD_MODULE_CTRL_UNBIND: 582 TAILQ_FOREACH_SAFE(ctrl, &self->ctrls, next, ctrlt) { 583 if (ctrl->peerid == imsg->hdr.peerid) { 584 TAILQ_REMOVE(&self->ctrls, ctrl, next); 585 free(ctrl); 586 break; 587 } 588 } 589 break; 590 case IMSG_RADIUSD_MODULE_IPCP_MONITOR: 591 case IMSG_RADIUSD_MODULE_IPCP_DUMP_AND_MONITOR: 592 if ((ctrl = calloc(1, sizeof(struct module_ipcp_ctrlconn))) 593 == NULL) { 594 log_warn("%s: calloc()", __func__); 595 goto fail; 596 } 597 ctrl->peerid = imsg->hdr.peerid; 598 TAILQ_INSERT_TAIL(&self->ctrls, ctrl, next); 599 module_imsg_compose(self->base, IMSG_RADIUSD_MODULE_CTRL_BIND, 600 imsg->hdr.peerid, 0, -1, NULL, 0); 601 if (imsg->hdr.type == IMSG_RADIUSD_MODULE_IPCP_MONITOR) 602 break; 603 /* FALLTHROUGH */ 604 case IMSG_RADIUSD_MODULE_IPCP_DUMP: 605 dumpsiz = MAX_IMSGSIZE; 606 if ((dump = calloc(1, dumpsiz)) == NULL) { 607 log_warn("%s: calloc()", __func__); 608 goto fail; 609 } 610 i = 0; 611 RB_FOREACH(assign, assigned_ipv4_tree, &self->ipv4s) { 612 if (!timespecisset(&assign->start)) 613 /* not started yet */ 614 continue; 615 ipcp_db_dump_fill_record(dump, i++, assign); 616 if (RB_NEXT(assigned_ipv4_tree, &self->ipv4s, assign) 617 == NULL) 618 break; 619 if (offsetof(struct radiusd_ipcp_db_dump, 620 records[i + 1]) >= dumpsiz) { 621 module_imsg_compose(self->base, 622 IMSG_RADIUSD_MODULE_IPCP_DUMP, 623 imsg->hdr.peerid, 0, -1, 624 dump, offsetof(struct radiusd_ipcp_db_dump, 625 records[i])); 626 i = 0; 627 } 628 } 629 dump->islast = 1; 630 module_imsg_compose(self->base, IMSG_RADIUSD_MODULE_IPCP_DUMP, 631 imsg->hdr.peerid, 0, -1, dump, offsetof( 632 struct radiusd_ipcp_db_dump, records[i])); 633 freezero(dump ,dumpsiz); 634 break; 635 case IMSG_RADIUSD_MODULE_IPCP_DISCONNECT: 636 case IMSG_RADIUSD_MODULE_IPCP_DELETE: 637 if (datalen < sizeof(unsigned)) { 638 log_warn("%s: received " 639 "%s message size is wrong", __func__, 640 (imsg->hdr.type == 641 IMSG_RADIUSD_MODULE_IPCP_DISCONNECT) 642 ? "IMSG_RADIUSD_MODULE_IPCP_DISCONNECT" 643 : "IMSG_RADIUSD_MODULE_IPCP_DELETE"); 644 goto fail; 645 } 646 seq = *(unsigned *)imsg->data; 647 RB_FOREACH(assign, assigned_ipv4_tree, &self->ipv4s) { 648 if (!timespecisset(&assign->start)) 649 /* not started yet */ 650 continue; 651 if (assign->seq == seq) 652 break; 653 } 654 if (assign == NULL) { 655 cause = "session not found"; 656 log_warnx("%s seq=%u requested, but the " 657 "session is not found", 658 (imsg->hdr.type == 659 IMSG_RADIUSD_MODULE_IPCP_DISCONNECT)? "Disconnect" 660 : "Delete", seq); 661 module_imsg_compose(self->base, IMSG_NG, 662 imsg->hdr.peerid, 0, -1, cause, strlen(cause) + 1); 663 } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_IPCP_DELETE) { 664 log_info("Delete seq=%u by request", assign->seq); 665 ipcp_ipv4_delete(self, assign, "By control"); 666 module_imsg_compose(self->base, IMSG_OK, 667 imsg->hdr.peerid, 0, -1, NULL, 0); 668 } else { 669 if (assign->dae == NULL) 670 log_warnx("Disconnect seq=%u requested, but " 671 "DAE is not configured", assign->seq); 672 else { 673 log_info("Disconnect seq=%u requested", 674 assign->seq); 675 if ((client = calloc(1, sizeof(struct 676 radiusctl_client))) == NULL) { 677 log_warn("%s: calloc: %m", 678 __func__); 679 goto fail; 680 } 681 client->peerid = imsg->hdr.peerid; 682 if (assign->dae_ntry == 0) 683 ipcp_dae_send_disconnect_request( 684 assign); 685 TAILQ_INSERT_TAIL(&assign->dae_clients, 686 client, entry); 687 } 688 } 689 break; 690 } 691 return; 692 fail: 693 module_stop(self->base); 694 } 695 696 int 697 ipcp_notice_startstop(struct module_ipcp *self, struct assigned_ipv4 *assign, 698 int start, struct radiusd_ipcp_statistics *stat) 699 { 700 struct module_ipcp_ctrlconn *ctrl; 701 struct radiusd_ipcp_db_dump *dump; 702 size_t dumpsiz; 703 struct iovec iov[2]; 704 int niov = 0; 705 706 dumpsiz = offsetof(struct radiusd_ipcp_db_dump, records[1]); 707 if ((dump = calloc(1, dumpsiz)) == NULL) { 708 log_warn("%s: calloc()", __func__); 709 return (-1); 710 } 711 dump->islast = 1; 712 ipcp_db_dump_fill_record(dump, 0, assign); 713 714 iov[niov].iov_base = dump; 715 iov[niov].iov_len = dumpsiz; 716 if (start == 0) { 717 iov[++niov].iov_base = stat; 718 iov[niov].iov_len = sizeof(struct radiusd_ipcp_statistics); 719 } 720 TAILQ_FOREACH(ctrl, &self->ctrls, next) 721 module_imsg_composev(self->base, 722 (start)? IMSG_RADIUSD_MODULE_IPCP_START : 723 IMSG_RADIUSD_MODULE_IPCP_STOP, ctrl->peerid, 0, -1, iov, 724 niov + 1); 725 freezero(dump, dumpsiz); 726 return (0); 727 } 728 729 void 730 ipcp_resdeco(void *ctx, u_int q_id, const u_char *req, size_t reqlen, 731 const u_char *res, size_t reslen) 732 { 733 struct module_ipcp *self = ctx; 734 RADIUS_PACKET *radres = NULL, *radreq = NULL; 735 struct in_addr addr4; 736 const struct in_addr mask4 = { .s_addr = 0xffffffffUL }; 737 int res_code, msraserr = 935; 738 struct ipcp_address *addr; 739 int i, n; 740 bool found = false; 741 char username[256], buf[128]; 742 struct user *user = NULL; 743 struct assigned_ipv4 *assigned = NULL, *assign; 744 745 ipcp_update_time(self); 746 747 if ((radres = radius_convert_packet(res, reslen)) == NULL) { 748 log_warn("%s: radius_convert_packet() failed", __func__); 749 goto fatal; 750 } 751 res_code = radius_get_code(radres); 752 if (res_code != RADIUS_CODE_ACCESS_ACCEPT) 753 goto accept; 754 755 if ((radreq = radius_convert_packet(req, reqlen)) == NULL) { 756 log_warn("%s: radius_convert_packet() failed", __func__); 757 goto fatal; 758 } 759 760 /* 761 * prefer User-Name of the response rather than the request, 762 * since it must be the authenticated user. 763 */ 764 if (radius_get_string_attr(radres, RADIUS_TYPE_USER_NAME, username, 765 sizeof(username)) != 0 && 766 radius_get_string_attr(radreq, RADIUS_TYPE_USER_NAME, username, 767 sizeof(username)) != 0) { 768 log_warnx("q=%u unexpected request: no user-name", q_id); 769 goto fatal; 770 } 771 772 if ((addr = TAILQ_FIRST(&self->addrs)) != NULL) { 773 /* The address assignment is configured */ 774 775 if ((user = ipcp_user_get(self, username)) == NULL) { 776 log_warn("%s: ipcp_user_get()", __func__); 777 goto fatal; 778 } 779 780 msraserr = 935; 781 if (self->max_sessions != 0) { 782 if (self->nsessions >= self->max_sessions) { 783 log_info("q=%u user=%s rejected: number of " 784 "sessions reached the limit(%d)", q_id, 785 user->name, self->max_sessions); 786 goto reject; 787 } 788 } 789 if (self->user_max_sessions != 0) { 790 n = 0; 791 TAILQ_FOREACH(assign, &user->ipv4s, next) 792 n++; 793 if (n >= self->user_max_sessions) { 794 log_info("q=%u user=%s rejected: number of " 795 "sessions per a user reached the limit(%d)", 796 q_id, user->name, self->user_max_sessions); 797 goto reject; 798 } 799 } 800 801 msraserr = 716; 802 if (radius_get_ipv4_attr(radres, 803 RADIUS_TYPE_FRAMED_IP_ADDRESS, &addr4) == 0) { 804 if (ipcp_ipv4_find(self, addr4) != NULL) 805 log_info("q=%u user=%s rejected: server " 806 "requested IP address is busy", q_id, 807 user->name); 808 else { 809 /* compare in host byte order */ 810 addr4.s_addr = ntohl(addr4.s_addr); 811 TAILQ_FOREACH(addr, &self->addrs, next) { 812 if (addr->type != ADDRESS_TYPE_STATIC && 813 addr->type != ADDRESS_TYPE_POOL) 814 continue; 815 if (addr->start.s_addr <= addr4.s_addr 816 && addr4.s_addr <= addr->end.s_addr) 817 break; 818 } 819 if (addr == NULL) 820 log_info("q=%u user=%s rejected: " 821 "server requested IP address is " 822 "out of the range", q_id, 823 user->name); 824 else 825 found = true; 826 /* revert the addr to the network byte order */ 827 addr4.s_addr = htonl(addr4.s_addr); 828 } 829 if (!found) 830 goto reject; 831 } else { 832 int inpool_idx = 0; 833 834 /* select a random address */ 835 n = arc4random_uniform(self->npools); 836 i = 0; 837 TAILQ_FOREACH(addr, &self->addrs, next) { 838 if (addr->type == ADDRESS_TYPE_POOL) { 839 if (i <= n && n < i + addr->naddrs) { 840 inpool_idx = n - i; 841 break; 842 } 843 i += addr->naddrs; 844 } 845 } 846 /* loop npools times until a free address is found */ 847 for (i = 0; i < self->npools && addr != NULL; i++) { 848 addr4.s_addr = htonl( 849 addr->start.s_addr + inpool_idx); 850 if (ipcp_ipv4_find(self, addr4) == NULL) { 851 found = true; 852 break; 853 } 854 /* try inpool_idx if it's in the range */ 855 if (++inpool_idx < addr->naddrs) 856 continue; 857 /* iterate addr to the next pool */ 858 do { 859 addr = TAILQ_NEXT(addr, next); 860 if (addr == NULL) 861 addr = TAILQ_FIRST( 862 &self->addrs); 863 } while (addr->type != ADDRESS_TYPE_POOL); 864 inpool_idx = 0; /* try the first */ 865 } 866 if (!found) { 867 log_info("q=%u user=%s rejected: ran out of " 868 "the address pool", q_id, user->name); 869 goto reject; 870 } 871 } 872 if ((assigned = ipcp_ipv4_assign(self, user, addr4)) == NULL) { 873 log_warn("%s: ipcp_ipv4_assign()", __func__); 874 goto fatal; 875 } 876 radius_set_ipv4_attr(radres, RADIUS_TYPE_FRAMED_IP_NETMASK, 877 mask4); 878 radius_del_attr_all(radres, RADIUS_TYPE_FRAMED_IP_ADDRESS); 879 radius_put_ipv4_attr(radres, RADIUS_TYPE_FRAMED_IP_ADDRESS, 880 addr4); 881 log_info("q=%u Assign %s for %s", q_id, 882 inet_ntop(AF_INET, &addr4, buf, sizeof(buf)), username); 883 if (radius_has_attr(radreq, RADIUS_TYPE_USER_PASSWORD)) 884 strlcpy(assigned->auth_method, "PAP", 885 sizeof(assigned->auth_method)); 886 else if (radius_has_attr(radreq, RADIUS_TYPE_CHAP_PASSWORD)) 887 strlcpy(assigned->auth_method, "CHAP", 888 sizeof(assigned->auth_method)); 889 else if (radius_has_vs_attr(radreq, RADIUS_VENDOR_MICROSOFT, 890 RADIUS_VTYPE_MS_CHAP_RESPONSE)) 891 strlcpy(assigned->auth_method, "MS-CHAP", 892 sizeof(assigned->auth_method)); 893 else if (radius_has_vs_attr(radreq, RADIUS_VENDOR_MICROSOFT, 894 RADIUS_VTYPE_MS_CHAP2_RESPONSE)) 895 strlcpy(assigned->auth_method, "MS-CHAP-V2", 896 sizeof(assigned->auth_method)); 897 else if (radius_has_attr(radreq, RADIUS_TYPE_EAP_MESSAGE)) 898 strlcpy(assigned->auth_method, "EAP", 899 sizeof(assigned->auth_method)); 900 901 radius_get_ipv4_attr(radreq, RADIUS_TYPE_NAS_IP_ADDRESS, 902 &assigned->nas_ipv4); 903 radius_get_ipv6_attr(radreq, RADIUS_TYPE_NAS_IPV6_ADDRESS, 904 &assigned->nas_ipv6); 905 radius_get_string_attr(radreq, RADIUS_TYPE_NAS_IDENTIFIER, 906 assigned->nas_id, sizeof(assigned->nas_id)); 907 } 908 909 if (self->name_server[0].s_addr != 0) { 910 addr4.s_addr = htonl(self->name_server[0].s_addr); 911 radius_del_vs_attr_all(radres, 912 RADIUS_VENDOR_MICROSOFT, 913 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER); 914 radius_put_vs_ipv4_attr(radres, 915 RADIUS_VENDOR_MICROSOFT, 916 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, self->name_server[0]); 917 } 918 if (self->name_server[1].s_addr != 0) { 919 addr4.s_addr = htonl(self->name_server[1].s_addr); 920 radius_del_vs_attr_all(radres, 921 RADIUS_VENDOR_MICROSOFT, 922 RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER); 923 radius_put_vs_ipv4_attr(radres, 924 RADIUS_VENDOR_MICROSOFT, 925 RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER, self->name_server[1]); 926 } 927 if (self->netbios_server[0].s_addr != 0) { 928 addr4.s_addr = htonl(self->netbios_server[0].s_addr); 929 radius_del_vs_attr_all(radres, 930 RADIUS_VENDOR_MICROSOFT, 931 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER); 932 radius_put_vs_ipv4_attr(radres, 933 RADIUS_VENDOR_MICROSOFT, 934 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, 935 self->netbios_server[0]); 936 } 937 if (self->netbios_server[1].s_addr != 0) { 938 addr4.s_addr = htonl(self->netbios_server[1].s_addr); 939 radius_del_vs_attr_all(radres, 940 RADIUS_VENDOR_MICROSOFT, 941 RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER); 942 radius_put_vs_ipv4_attr(radres, 943 RADIUS_VENDOR_MICROSOFT, 944 RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER, 945 self->netbios_server[1]); 946 } 947 if (!self->no_session_timeout && assigned != NULL && 948 radius_has_attr(radres, RADIUS_TYPE_SESSION_TIMEOUT)) { 949 radius_get_uint32_attr(radres, RADIUS_TYPE_SESSION_TIMEOUT, 950 &assigned->session_timeout); 951 /* we handle this session-timeout */ 952 radius_del_attr_all(radres, RADIUS_TYPE_SESSION_TIMEOUT); 953 } 954 955 accept: 956 if (module_resdeco_done(self->base, q_id, radius_get_data(radres), 957 radius_get_length(radres)) == -1) { 958 log_warn("%s: module_resdeco_done() failed", __func__); 959 module_stop(self->base); 960 } 961 if (radreq != NULL) 962 radius_delete_packet(radreq); 963 radius_delete_packet(radres); 964 return; 965 reject: 966 ipcp_reject(self, radreq, q_id, radres, msraserr); 967 radius_delete_packet(radreq); 968 radius_delete_packet(radres); 969 return; 970 fatal: 971 if (radreq != NULL) 972 radius_delete_packet(radreq); 973 if (radres != NULL) 974 radius_delete_packet(radres); 975 module_stop(self->base); 976 } 977 978 void 979 ipcp_reject(struct module_ipcp *self, RADIUS_PACKET *reqp, unsigned int q_id, 980 RADIUS_PACKET *orig_resp, int mserr) 981 { 982 bool is_eap, is_mschap, is_mschap2; 983 uint8_t attr[256]; 984 size_t attrlen; 985 RADIUS_PACKET *resp; 986 struct { 987 uint8_t code; 988 uint8_t id; 989 uint16_t length; 990 } __packed eap; 991 992 resp = radius_new_response_packet(RADIUS_CODE_ACCESS_REJECT, reqp); 993 if (resp == NULL) { 994 log_warn("%s: radius_new_response_packet() failed", __func__); 995 module_accsreq_aborted(self->base, q_id); 996 return; 997 } 998 999 is_eap = radius_has_attr(reqp, RADIUS_TYPE_EAP_MESSAGE); 1000 if (radius_get_vs_raw_attr(reqp, RADIUS_VENDOR_MICROSOFT, 1001 RADIUS_VTYPE_MS_CHAP_RESPONSE, attr, &attrlen) == 0) 1002 is_mschap = true; 1003 else if (radius_get_vs_raw_attr(reqp, RADIUS_VENDOR_MICROSOFT, 1004 RADIUS_VTYPE_MS_CHAP2_RESPONSE, attr, &attrlen) == 0) 1005 is_mschap2 = true; 1006 1007 if (is_eap) { 1008 memset(&eap, 0, sizeof(eap)); /* just in case */ 1009 eap.code = 1; /* EAP Request */ 1010 attrlen = sizeof(attr); 1011 if (orig_resp != NULL && radius_get_raw_attr(orig_resp, 1012 RADIUS_TYPE_EAP_MESSAGE, &attr, &attrlen) == 0) 1013 eap.id = attr[1]; 1014 else 1015 eap.id = 0; 1016 eap.length = htons(sizeof(eap)); 1017 radius_put_raw_attr(resp, RADIUS_TYPE_EAP_MESSAGE, &eap, 1018 ntohs(eap.length)); 1019 } else if (is_mschap || is_mschap2) { 1020 attr[0] = attr[1]; /* Copy the ident of the request */ 1021 snprintf(attr + 1, sizeof(attr) - 1, "E=%d R=0 V=3", mserr); 1022 radius_put_vs_raw_attr(resp, RADIUS_VENDOR_MICROSOFT, 1023 RADIUS_VTYPE_MS_CHAP_ERROR, attr, strlen(attr + 1) + 1); 1024 } 1025 1026 module_resdeco_done(self->base, q_id, radius_get_data(resp), 1027 radius_get_length(resp)); 1028 radius_delete_packet(resp); 1029 } 1030 1031 /*********************************************************************** 1032 * RADIUS Accounting 1033 ***********************************************************************/ 1034 void 1035 ipcp_accounting_request(void *ctx, u_int q_id, const u_char *pkt, 1036 size_t pktlen) 1037 { 1038 RADIUS_PACKET *radpkt = NULL; 1039 int code, af; 1040 uint32_t type, delay, uval; 1041 struct in_addr addr4, nas_ipv4; 1042 struct in6_addr nas_ipv6, ipv6_zero; 1043 struct module_ipcp *self = ctx; 1044 struct assigned_ipv4 *assign, *assignt; 1045 char username[256], nas_id[256], buf[256], 1046 buf1[384]; 1047 struct timespec dur; 1048 struct radiusd_ipcp_statistics 1049 stat; 1050 struct module_ipcp_dae *dae; 1051 1052 ipcp_update_time(self); 1053 1054 if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) { 1055 log_warn("%s: radius_convert_packet() failed", __func__); 1056 module_stop(self->base); 1057 return; 1058 } 1059 code = radius_get_code(radpkt); 1060 if (code != RADIUS_CODE_ACCOUNTING_REQUEST && 1061 code != RADIUS_CODE_ACCOUNTING_RESPONSE) 1062 goto out; 1063 1064 if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_STATUS_TYPE, &type) 1065 != 0) 1066 goto out; 1067 1068 /* identifier for the NAS */ 1069 memset(&ipv6_zero, 0, sizeof(ipv6_zero)); 1070 memset(&nas_ipv4, 0, sizeof(nas_ipv4)); 1071 memset(&nas_ipv6, 0, sizeof(nas_ipv6)); 1072 memset(&nas_id, 0, sizeof(nas_id)); 1073 1074 radius_get_ipv4_attr(radpkt, RADIUS_TYPE_NAS_IP_ADDRESS, &nas_ipv4); 1075 radius_get_ipv6_attr(radpkt, RADIUS_TYPE_NAS_IPV6_ADDRESS, &nas_ipv6); 1076 radius_get_string_attr(radpkt, RADIUS_TYPE_NAS_IDENTIFIER, nas_id, 1077 sizeof(nas_id)); 1078 1079 if (nas_ipv4.s_addr == 0 && IN6_ARE_ADDR_EQUAL(&nas_ipv6, &ipv6_zero) && 1080 nas_id[0] == '\0') { 1081 log_warnx("q=%u no NAS-IP-Address, NAS-IPV6-Address, or " 1082 "NAS-Identifier", q_id); 1083 goto out; 1084 } 1085 1086 if (type == RADIUS_ACCT_STATUS_TYPE_ACCT_ON || 1087 type == RADIUS_ACCT_STATUS_TYPE_ACCT_OFF) { 1088 /* 1089 * NAS or daemon is restarted. Delete all assigned records 1090 * from it 1091 */ 1092 RB_FOREACH_SAFE(assign, assigned_ipv4_tree, &self->ipv4s, 1093 assignt) { 1094 if (assign->nas_ipv4.s_addr != nas_ipv4.s_addr || 1095 !IN6_ARE_ADDR_EQUAL(&assign->nas_ipv6, &nas_ipv6) || 1096 strcmp(assign->nas_id, nas_id) != 0) 1097 continue; 1098 log_info("q=%u Delete record for %s", q_id, 1099 inet_ntop(AF_INET, &assign->ipv4, buf, 1100 sizeof(buf))); 1101 ipcp_ipv4_delete(self, assign, 1102 (type == RADIUS_ACCT_STATUS_TYPE_ACCT_ON) 1103 ? "Receive Acct-On" : "Receive Acct-Off"); 1104 } 1105 return; 1106 } 1107 1108 if (radius_get_ipv4_attr(radpkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, &addr4) 1109 != 0) { 1110 log_warnx("q=%u no Framed-IP-Address-Address attribute", q_id); 1111 goto out; 1112 } 1113 if (radius_get_string_attr(radpkt, RADIUS_TYPE_USER_NAME, username, 1114 sizeof(username)) != 0) { 1115 log_warnx("q=%u no User-Name attribute", q_id); 1116 goto out; 1117 } 1118 if ((assign = ipcp_ipv4_find(self, addr4)) == NULL) { 1119 /* not assigned by this */ 1120 log_warnx("q=%u %s is not assigned by us", q_id, 1121 inet_ntop(AF_INET, &addr4, buf, sizeof(buf))); 1122 goto out; 1123 } 1124 1125 if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_DELAY_TIME, &delay) 1126 != 0) 1127 delay = 0; 1128 1129 if (type == RADIUS_ACCT_STATUS_TYPE_START) { 1130 assign->start = self->uptime; 1131 assign->start.tv_sec -= delay; 1132 1133 if (!self->no_session_timeout && (self->session_timeout > 0 || 1134 assign->session_timeout > 0)) { 1135 assign->timeout = assign->start; 1136 if (self->session_timeout > 0) 1137 assign->timeout.tv_sec += self->session_timeout; 1138 else 1139 assign->timeout.tv_sec += 1140 assign->session_timeout; 1141 } 1142 assign->nas_ipv4 = nas_ipv4; 1143 assign->nas_ipv6 = nas_ipv6; 1144 strlcpy(assign->nas_id, nas_id, sizeof(assign->nas_id)); 1145 1146 if (radius_get_string_attr(radpkt, RADIUS_TYPE_ACCT_SESSION_ID, 1147 assign->session_id, sizeof(assign->session_id)) != 0) 1148 assign->session_id[0] = '\0'; 1149 if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_TUNNEL_TYPE, 1150 &uval) == 0) 1151 assign->tun_type = radius_tunnel_type_string(uval, 1152 NULL); 1153 if (assign->tun_type == NULL) 1154 assign->tun_type = ""; 1155 1156 /* 1157 * Get "tunnel from" from Tunnel-Client-Endpoint or Calling- 1158 * Station-Id 1159 */ 1160 af = AF_UNSPEC; 1161 if (radius_get_string_attr(radpkt, 1162 RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT, buf, sizeof(buf)) == 0) 1163 { 1164 if (radius_get_uint32_attr(radpkt, 1165 RADIUS_TYPE_TUNNEL_MEDIUM_TYPE, &uval) == 0) { 1166 if (uval == RADIUS_TUNNEL_MEDIUM_TYPE_IPV4) 1167 af = AF_INET; 1168 else if (uval == RADIUS_TUNNEL_MEDIUM_TYPE_IPV6) 1169 af = AF_INET6; 1170 } 1171 parse_addr(buf, af, (struct sockaddr *) 1172 &assign->tun_client, sizeof(assign->tun_client)); 1173 } 1174 if (assign->tun_client.sin4.sin_family == 0 && 1175 radius_get_string_attr(radpkt, 1176 RADIUS_TYPE_CALLING_STATION_ID, buf, sizeof(buf)) == 0) 1177 parse_addr(buf, af, (struct sockaddr *) 1178 &assign->tun_client, sizeof(assign->tun_client)); 1179 1180 TAILQ_FOREACH(dae, &self->daes, next) { 1181 if (dae->nas_id[0] == '\0' || 1182 strcmp(dae->nas_id, assign->nas_id) == 0) 1183 break; 1184 } 1185 assign->dae = dae; 1186 1187 ipcp_put_db(self, assign); 1188 ipcp_schedule_timer(self); 1189 1190 if (ipcp_notice_startstop(self, assign, 1, NULL) != 0) 1191 goto fail; 1192 log_info("q=%u Start seq=%u user=%s duration=%dsec " 1193 "session=%s tunnel=%s from=%s auth=%s ip=%s", q_id, 1194 assign->seq, assign->user->name, delay, assign->session_id, 1195 assign->tun_type, print_addr((struct sockaddr *) 1196 &assign->tun_client, buf1, sizeof(buf1)), 1197 assign->auth_method, inet_ntop(AF_INET, &addr4, buf, 1198 sizeof(buf))); 1199 } else if (type == RADIUS_ACCT_STATUS_TYPE_STOP) { 1200 memset(&stat, 0, sizeof(stat)); 1201 1202 dur = self->uptime; 1203 dur.tv_sec -= delay; 1204 timespecsub(&dur, &assign->start, &dur); 1205 1206 if (radius_get_uint32_attr(radpkt, 1207 RADIUS_TYPE_ACCT_INPUT_OCTETS, &uval) == 0) 1208 stat.ibytes = uval; 1209 if (radius_get_uint32_attr(radpkt, 1210 RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, &uval) == 0) 1211 stat.ibytes = ((uint64_t)uval << 32) | stat.ibytes; 1212 if (radius_get_uint32_attr(radpkt, 1213 RADIUS_TYPE_ACCT_OUTPUT_OCTETS, &uval) == 0) 1214 stat.obytes = uval; 1215 if (radius_get_uint32_attr(radpkt, 1216 RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS, &uval) == 0) 1217 stat.obytes = ((uint64_t)uval << 32) | stat.obytes; 1218 radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_INPUT_PACKETS, 1219 &stat.ipackets); 1220 radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS, 1221 &stat.opackets); 1222 1223 if (radius_get_uint32_attr(radpkt, 1224 RADIUS_TYPE_ACCT_TERMINATE_CAUSE, &uval) == 0) 1225 strlcpy(stat.cause, radius_terminate_cause_string(uval), 1226 sizeof(stat.cause)); 1227 1228 log_info("q=%u Stop seq=%u user=%s duration=%lldsec " 1229 "session=%s tunnel=%s from=%s auth=%s ip=%s " 1230 "datain=%"PRIu64"bytes,%" PRIu32"packets dataout=%"PRIu64 1231 "bytes,%"PRIu32"packets cause=\"%s\"", q_id, 1232 assign->seq, assign->user->name, dur.tv_sec, 1233 assign->session_id, assign->tun_type, print_addr( 1234 (struct sockaddr *)&assign->tun_client, buf1, sizeof(buf1)), 1235 assign->auth_method, inet_ntop(AF_INET, &addr4, buf, 1236 sizeof(buf)), stat.ibytes, stat.ipackets, stat.obytes, 1237 stat.opackets, stat.cause); 1238 1239 ipcp_del_db(self, assign); 1240 if (ipcp_notice_startstop(self, assign, 0, &stat) != 0) 1241 goto fail; 1242 ipcp_ipv4_release(self, ipcp_ipv4_find(self, addr4)); 1243 } 1244 out: 1245 radius_delete_packet(radpkt); 1246 return; 1247 fail: 1248 module_stop(self->base); 1249 radius_delete_packet(radpkt); 1250 return; 1251 } 1252 1253 /*********************************************************************** 1254 * On memory database to manage IP address assignment 1255 ***********************************************************************/ 1256 struct assigned_ipv4 * 1257 ipcp_ipv4_assign(struct module_ipcp *self, struct user *user, 1258 struct in_addr ina) 1259 { 1260 struct assigned_ipv4 *ip; 1261 1262 ip = calloc(1, sizeof(struct assigned_ipv4)); 1263 if (ip == NULL) { 1264 log_warn("%s: calloc()", __func__); 1265 return (NULL); 1266 } 1267 ip->ipv4 = ina; 1268 ip->user = user; 1269 ip->authtime = self->uptime; 1270 RB_INSERT(assigned_ipv4_tree, &self->ipv4s, ip); 1271 TAILQ_INSERT_TAIL(&user->ipv4s, ip, next); 1272 TAILQ_INIT(&ip->dae_clients); 1273 self->nsessions++; 1274 ip->seq = self->seq++; 1275 1276 return (ip); 1277 } 1278 1279 struct assigned_ipv4 * 1280 ipcp_ipv4_find(struct module_ipcp *self, struct in_addr ina) 1281 { 1282 struct assigned_ipv4 key, *ret; 1283 struct timespec dif; 1284 1285 key.ipv4 = ina; 1286 ret = RB_FIND(assigned_ipv4_tree, &self->ipv4s, &key); 1287 if (ret != NULL && ret->start.tv_sec == 0) { 1288 /* not yet assigned */ 1289 timespecsub(&self->uptime, &ret->authtime, &dif); 1290 if (dif.tv_sec >= self->start_wait) { 1291 /* assumed NAS finally didn't use the address */ 1292 TAILQ_REMOVE(&ret->user->ipv4s, ret, next); 1293 RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, ret); 1294 free(ret); 1295 ret = NULL; 1296 self->nsessions--; 1297 } 1298 } 1299 return (ret); 1300 } 1301 1302 void 1303 ipcp_ipv4_delete(struct module_ipcp *self, struct assigned_ipv4 *assign, 1304 const char *cause) 1305 { 1306 struct radiusd_ipcp_statistics stat; 1307 1308 memset(&stat, 0, sizeof(stat)); 1309 strlcpy(stat.cause, cause, sizeof(stat.cause)); 1310 1311 ipcp_del_db(self, assign); 1312 ipcp_notice_startstop(self, assign, 0, &stat); 1313 ipcp_ipv4_release(self, assign); 1314 } 1315 1316 void 1317 ipcp_ipv4_release(struct module_ipcp *self, struct assigned_ipv4 *assign) 1318 { 1319 if (assign != NULL) { 1320 TAILQ_REMOVE(&assign->user->ipv4s, assign, next); 1321 RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, assign); 1322 self->nsessions--; 1323 ipcp_dae_reset_request(assign); 1324 free(assign); 1325 } 1326 } 1327 1328 int 1329 assigned_ipv4_compar(struct assigned_ipv4 *a, struct assigned_ipv4 *b) 1330 { 1331 if (a->ipv4.s_addr > b->ipv4.s_addr) 1332 return (1); 1333 else if (a->ipv4.s_addr < b->ipv4.s_addr) 1334 return (-1); 1335 return (0); 1336 } 1337 1338 struct user * 1339 ipcp_user_get(struct module_ipcp *self, const char *username) 1340 { 1341 struct { 1342 struct user user; 1343 char name[256]; 1344 } key; 1345 struct user *elm; 1346 1347 strlcpy(key.user.name, username, 256); 1348 elm = RB_FIND(user_tree, &self->users, &key.user); 1349 if (elm == NULL) { 1350 if ((elm = calloc(1, offsetof(struct user, name[ 1351 strlen(username) + 1]))) == NULL) 1352 return (NULL); 1353 memcpy(elm->name, username, strlen(username)); 1354 RB_INSERT(user_tree, &self->users, elm); 1355 TAILQ_INIT(&elm->ipv4s); 1356 } 1357 1358 return (elm); 1359 } 1360 1361 int 1362 user_compar(struct user *a, struct user *b) 1363 { 1364 return (strcmp(a->name, b->name)); 1365 } 1366 1367 RB_GENERATE_STATIC(assigned_ipv4_tree, assigned_ipv4, tree, 1368 assigned_ipv4_compar); 1369 RB_GENERATE_STATIC(user_tree, user, tree, user_compar); 1370 1371 /*********************************************************************** 1372 * DB for the persistent over processes 1373 ***********************************************************************/ 1374 int 1375 ipcp_prepare_db(void) 1376 { 1377 struct passwd *pw; 1378 DB *db; 1379 1380 if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_CREAT | O_RDWR | O_EXLOCK, 1381 0600, DB_BTREE, NULL)) == NULL) 1382 return (-1); 1383 if ((pw = getpwnam(RADIUSD_USER)) == NULL) 1384 return (-1); 1385 fchown(db->fd(db), pw->pw_uid, pw->pw_gid); 1386 db->close(db); 1387 1388 return (0); 1389 } 1390 1391 int 1392 ipcp_restore_from_db(struct module_ipcp *self) 1393 { 1394 DB *db; 1395 DBT key, val; 1396 char keybuf[128]; 1397 struct user *user; 1398 struct radiusd_ipcp_db_record 1399 *record; 1400 struct assigned_ipv4 *assigned; 1401 struct in_addr ipv4; 1402 struct module_ipcp_dae *dae; 1403 1404 if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDONLY | O_SHLOCK, 0600, 1405 DB_BTREE, NULL)) == NULL) 1406 return (-1); 1407 1408 key.data = "ipv4/"; 1409 key.size = 5; 1410 if (db->seq(db, &key, &val, R_CURSOR) == 0) { 1411 do { 1412 if (key.size >= sizeof(keybuf)) 1413 break; 1414 memcpy(keybuf, key.data, key.size); 1415 keybuf[key.size] = '\0'; 1416 if (strncmp(keybuf, "ipv4/", 5) != 0) 1417 break; 1418 inet_pton(AF_INET, keybuf + 5, &ipv4); 1419 record = (struct radiusd_ipcp_db_record *)val.data; 1420 if ((user = ipcp_user_get(self, record->username)) 1421 == NULL) 1422 return (-1); 1423 if ((assigned = ipcp_ipv4_assign(self, user, ipv4)) 1424 == NULL) 1425 return (-1); 1426 assigned->seq = record->seq; 1427 self->seq = MAXIMUM(assigned->seq + 1, self->seq); 1428 strlcpy(assigned->auth_method, record->auth_method, 1429 sizeof(assigned->auth_method)); 1430 strlcpy(assigned->session_id, record->session_id, 1431 sizeof(assigned->session_id)); 1432 assigned->start = record->start; 1433 assigned->timeout = record->timeout; 1434 assigned->nas_ipv4 = record->nas_ipv4; 1435 assigned->nas_ipv6 = record->nas_ipv6; 1436 strlcpy(assigned->nas_id, record->nas_id, 1437 sizeof(assigned->nas_id)); 1438 assigned->tun_type = radius_tunnel_type_string(0, 1439 record->tun_type); 1440 memcpy(&assigned->tun_client, &record->tun_client, 1441 sizeof(assigned->tun_client)); 1442 1443 TAILQ_FOREACH(dae, &self->daes, next) { 1444 if (dae->nas_id[0] == '\0' || 1445 strcmp(dae->nas_id, assigned->nas_id) == 0) 1446 break; 1447 } 1448 assigned->dae = dae; 1449 } while (db->seq(db, &key, &val, R_NEXT) == 0); 1450 } 1451 db->close(db); 1452 1453 return (0); 1454 } 1455 1456 void 1457 ipcp_put_db(struct module_ipcp *self, struct assigned_ipv4 *assigned) 1458 { 1459 DB *db; 1460 DBT key, val; 1461 char keybuf[128]; 1462 struct radiusd_ipcp_db_record 1463 record; 1464 1465 strlcpy(keybuf, "ipv4/", sizeof(keybuf)); 1466 inet_ntop(AF_INET, &assigned->ipv4, keybuf + 5, sizeof(keybuf) - 5); 1467 key.data = keybuf; 1468 key.size = strlen(keybuf); 1469 strlcpy(record.session_id, assigned->session_id, 1470 sizeof(record.session_id)); 1471 strlcpy(record.auth_method, assigned->auth_method, 1472 sizeof(record.auth_method)); 1473 strlcpy(record.username, assigned->user->name, sizeof(record.username)); 1474 record.seq = assigned->seq; 1475 record.start = assigned->start; 1476 record.timeout = assigned->timeout; 1477 record.nas_ipv4 = assigned->nas_ipv4; 1478 record.nas_ipv6 = assigned->nas_ipv6; 1479 strlcpy(record.nas_id, assigned->nas_id, sizeof(record.nas_id)); 1480 if (assigned->tun_type != NULL) 1481 strlcpy(record.tun_type, assigned->tun_type, 1482 sizeof(record.tun_type)); 1483 memcpy(&record.tun_client, &assigned->tun_client, 1484 sizeof(record.tun_client)); 1485 1486 val.data = &record; 1487 val.size = sizeof(record); 1488 if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDWR | O_EXLOCK, 0600, 1489 DB_BTREE, NULL)) == NULL) 1490 return; 1491 db->put(db, &key, &val, 0); 1492 db->close(db); 1493 } 1494 1495 void 1496 ipcp_del_db(struct module_ipcp *self, struct assigned_ipv4 *assigned) 1497 { 1498 DB *db; 1499 DBT key; 1500 char keybuf[128]; 1501 1502 strlcpy(keybuf, "ipv4/", sizeof(keybuf)); 1503 inet_ntop(AF_INET, &assigned->ipv4, keybuf + 5, sizeof(keybuf) - 5); 1504 key.data = keybuf; 1505 key.size = strlen(keybuf); 1506 1507 if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDWR | O_EXLOCK, 0600, 1508 DB_BTREE, NULL)) == NULL) 1509 return; 1510 db->del(db, &key, 0); 1511 db->close(db); 1512 } 1513 1514 void 1515 ipcp_db_dump_fill_record(struct radiusd_ipcp_db_dump *dump, int idx, 1516 struct assigned_ipv4 *assign) 1517 { 1518 dump->records[idx].af = AF_INET; 1519 dump->records[idx].addr.ipv4 = assign->ipv4; 1520 dump->records[idx].rec.seq = assign->seq; 1521 strlcpy(dump->records[idx].rec.session_id, assign->session_id, 1522 sizeof(dump->records[idx].rec.session_id)); 1523 strlcpy(dump->records[idx].rec.auth_method, assign->auth_method, 1524 sizeof(dump->records[idx].rec.auth_method)); 1525 strlcpy(dump->records[idx].rec.username, assign->user->name, 1526 sizeof(dump->records[idx].rec.username)); 1527 dump->records[idx].rec.start = assign->start; 1528 dump->records[idx].rec.timeout = assign->timeout; 1529 dump->records[idx].rec.nas_ipv4 = assign->nas_ipv4; 1530 dump->records[idx].rec.nas_ipv6 = assign->nas_ipv6; 1531 strlcpy(dump->records[idx].rec.nas_id, assign->nas_id, 1532 sizeof(dump->records[idx].rec.nas_id)); 1533 if (assign->tun_type != NULL) 1534 strlcpy(dump->records[idx].rec.tun_type, assign->tun_type, 1535 sizeof(dump->records[idx].rec.tun_type)); 1536 memcpy(&dump->records[idx].rec.tun_client, &assign->tun_client, 1537 sizeof(dump->records[idx].rec.tun_client)); 1538 } 1539 1540 /*********************************************************************** 1541 * Timer 1542 ***********************************************************************/ 1543 void 1544 ipcp_update_time(struct module_ipcp *self) 1545 { 1546 clock_gettime(CLOCK_BOOTTIME, &self->uptime); 1547 } 1548 1549 void 1550 ipcp_on_timer(int fd, short ev, void *ctx) 1551 { 1552 struct module_ipcp *self = ctx; 1553 1554 ipcp_update_time(self); 1555 ipcp_schedule_timer(self); 1556 } 1557 1558 void 1559 ipcp_schedule_timer(struct module_ipcp *self) 1560 { 1561 struct assigned_ipv4 *assign, *min_assign = NULL; 1562 struct timespec tsd; 1563 struct timeval tv; 1564 1565 /* check session timeout */ 1566 RB_FOREACH(assign, assigned_ipv4_tree, &self->ipv4s) { 1567 if (assign->timeout.tv_sec == 0) 1568 continue; 1569 if (timespeccmp(&assign->timeout, &self->uptime, <=)) { 1570 log_info("Reached session timeout seq=%u", assign->seq); 1571 ipcp_dae_send_disconnect_request(assign); 1572 memset(&assign->timeout, 0, sizeof(assign->timeout)); 1573 ipcp_put_db(self, assign); 1574 } 1575 if (min_assign == NULL || 1576 timespeccmp(&min_assign->timeout, &assign->timeout, >)) 1577 min_assign = assign; 1578 } 1579 if (evtimer_pending(&self->ev_timer, NULL)) 1580 evtimer_del(&self->ev_timer); 1581 1582 if (min_assign != NULL) { 1583 timespecsub(&min_assign->timeout, &self->uptime, &tsd); 1584 TIMESPEC_TO_TIMEVAL(&tv, &tsd); 1585 evtimer_set(&self->ev_timer, ipcp_on_timer, self); 1586 evtimer_add(&self->ev_timer, &tv); 1587 } 1588 } 1589 1590 /*********************************************************************** 1591 * Dynamic Authorization Extension for RAIDUS (RFC 5176) 1592 ***********************************************************************/ 1593 static const int dae_request_timeouts[] = { 2, 4, 8, 8 }; 1594 1595 void 1596 ipcp_dae_send_disconnect_request(struct assigned_ipv4 *assign) 1597 { 1598 RADIUS_PACKET *reqpkt = NULL; 1599 struct timeval tv; 1600 char buf[80]; 1601 1602 if (assign->dae == NULL) 1603 return; /* DAE is not configured */ 1604 1605 if (assign->dae_reqpkt == NULL) { 1606 if ((reqpkt = radius_new_request_packet( 1607 RADIUS_CODE_DISCONNECT_REQUEST)) == NULL) { 1608 log_warn("%s: radius_new_request_packet(): %m", 1609 __func__); 1610 return; 1611 } 1612 radius_put_string_attr(reqpkt, RADIUS_TYPE_ACCT_SESSION_ID, 1613 assign->session_id); 1614 /* 1615 * RFC 5176 Section 3, "either the User-Name or 1616 * Chargeable-User-Identity attribute SHOULD be present in 1617 * Disconnect-Request and CoA-Request packets." 1618 */ 1619 radius_put_string_attr(reqpkt, RADIUS_TYPE_USER_NAME, 1620 assign->user->name); 1621 if (assign->nas_id[0] != '\0') 1622 radius_put_string_attr(reqpkt, 1623 RADIUS_TYPE_NAS_IDENTIFIER, assign->nas_id); 1624 if (ntohl(assign->nas_ipv4.s_addr) != 0) 1625 radius_put_ipv4_attr(reqpkt, 1626 RADIUS_TYPE_NAS_IP_ADDRESS, assign->nas_ipv4); 1627 if (!IN6_IS_ADDR_UNSPECIFIED(&assign->nas_ipv6)) 1628 radius_put_ipv6_attr(reqpkt, 1629 RADIUS_TYPE_NAS_IPV6_ADDRESS, &assign->nas_ipv6); 1630 radius_set_accounting_request_authenticator(reqpkt, 1631 assign->dae->secret); 1632 assign->dae_reqpkt = reqpkt; 1633 TAILQ_INSERT_TAIL(&assign->dae->reqs, assign, dae_next); 1634 } 1635 1636 if (assign->dae_ntry == 0) { 1637 if (assign->dae->ninflight >= RADIUSD_IPCP_DAE_MAX_INFLIGHT) 1638 return; 1639 log_info("Sending Disconnect-Request seq=%u to %s", 1640 assign->seq, print_addr((struct sockaddr *) 1641 &assign->dae->nas_addr, buf, sizeof(buf))); 1642 } 1643 1644 if (radius_send(assign->dae->sock, assign->dae_reqpkt, 0) < 0) 1645 log_warn("%s: sendto: %m", __func__); 1646 1647 tv.tv_sec = dae_request_timeouts[assign->dae_ntry]; 1648 tv.tv_usec = 0; 1649 evtimer_set(&assign->dae_evtimer, ipcp_dae_request_on_timeout, assign); 1650 evtimer_add(&assign->dae_evtimer, &tv); 1651 if (assign->dae_ntry == 0) 1652 assign->dae->ninflight++; 1653 assign->dae_ntry++; 1654 } 1655 1656 void 1657 ipcp_dae_request_on_timeout(int fd, short ev, void *ctx) 1658 { 1659 struct assigned_ipv4 *assign = ctx; 1660 char buf[80]; 1661 struct radiusctl_client *client; 1662 1663 if (assign->dae_ntry >= (int)nitems(dae_request_timeouts)) { 1664 log_warnx("No answer for Disconnect-Request seq=%u from %s", 1665 assign->seq, print_addr((struct sockaddr *) 1666 &assign->dae->nas_addr, buf, sizeof(buf))); 1667 TAILQ_FOREACH(client, &assign->dae_clients, entry) 1668 module_imsg_compose(assign->dae->ipcp->base, IMSG_NG, 1669 client->peerid, 0, -1, NULL, 0); 1670 ipcp_dae_reset_request(assign); 1671 } else 1672 ipcp_dae_send_disconnect_request(assign); 1673 } 1674 1675 void 1676 ipcp_dae_on_event(int fd, short ev, void *ctx) 1677 { 1678 struct module_ipcp_dae *dae = ctx; 1679 struct module_ipcp *self = dae->ipcp; 1680 RADIUS_PACKET *radres = NULL; 1681 int code; 1682 uint32_t u32; 1683 struct assigned_ipv4 *assign; 1684 char buf[80], causestr[80]; 1685 const char *cause = ""; 1686 struct radiusctl_client *client; 1687 1688 ipcp_update_time(self); 1689 1690 if ((ev & EV_READ) == 0) 1691 return; 1692 1693 if ((radres = radius_recv(dae->sock, 0)) == NULL) { 1694 if (errno == EAGAIN) 1695 return; 1696 log_warn("%s: Failed to receive from %s", __func__, print_addr( 1697 (struct sockaddr *)&dae->nas_addr, buf, sizeof(buf))); 1698 return; 1699 } 1700 TAILQ_FOREACH(assign, &dae->reqs, dae_next) { 1701 if (radius_get_id(assign->dae_reqpkt) == radius_get_id(radres)) 1702 break; 1703 } 1704 if (assign == NULL) { 1705 log_warnx("%s: Received RADIUS packet from %s has unknown " 1706 "id=%d", __func__, print_addr((struct sockaddr *) 1707 &dae->nas_addr, buf, sizeof(buf)), radius_get_id(radres)); 1708 goto out; 1709 } 1710 1711 radius_set_request_packet(radres, assign->dae_reqpkt); 1712 if ((radius_check_response_authenticator(radres, dae->secret)) != 0) { 1713 log_warnx("%s: Received RADIUS packet for seq=%u from %s has " 1714 "a bad authenticator", __func__, assign->seq, print_addr( 1715 (struct sockaddr *)&dae->nas_addr, buf, 1716 sizeof(buf))); 1717 goto out; 1718 } 1719 causestr[0] = '\0'; 1720 if (radius_get_uint32_attr(radres, RADIUS_TYPE_ERROR_CAUSE, &u32) == 0){ 1721 cause = radius_error_cause_string(u32); 1722 if (cause != NULL) 1723 snprintf(causestr, sizeof(causestr), " cause=%u(%s)", 1724 u32, cause); 1725 else 1726 snprintf(causestr, sizeof(causestr), " cause=%u", u32); 1727 cause = causestr; 1728 } 1729 1730 code = radius_get_code(radres); 1731 switch (code) { 1732 case RADIUS_CODE_DISCONNECT_ACK: 1733 log_info("Received Disconnect-ACK for seq=%u from %s%s", 1734 assign->seq, print_addr((struct sockaddr *) 1735 &dae->nas_addr, buf, sizeof(buf)), cause); 1736 break; 1737 case RADIUS_CODE_DISCONNECT_NAK: 1738 log_info("Received Disconnect-NAK for seq=%u from %s%s", 1739 assign->seq, print_addr((struct sockaddr *) 1740 &dae->nas_addr, buf, sizeof(buf)), cause); 1741 break; 1742 default: 1743 log_warn("%s: Received unknown code=%d for id=%u from %s", 1744 __func__, code, assign->seq, print_addr((struct sockaddr *) 1745 &dae->nas_addr, buf, sizeof(buf))); 1746 break; 1747 } 1748 1749 TAILQ_FOREACH(client, &assign->dae_clients, entry) { 1750 if (*cause != '\0') 1751 module_imsg_compose(self->base, 1752 (code == RADIUS_CODE_DISCONNECT_ACK) 1753 ? IMSG_OK : IMSG_NG, client->peerid, 0, -1, 1754 cause + 1, strlen(cause + 1) + 1); 1755 else 1756 module_imsg_compose(self->base, 1757 (code == RADIUS_CODE_DISCONNECT_ACK) 1758 ? IMSG_OK : IMSG_NG, client->peerid, 0, -1, 1759 NULL, 0); 1760 } 1761 ipcp_dae_reset_request(assign); 1762 out: 1763 if (radres != NULL) 1764 radius_delete_packet(radres); 1765 } 1766 1767 void 1768 ipcp_dae_reset_request(struct assigned_ipv4 *assign) 1769 { 1770 struct radiusctl_client *client, *clientt; 1771 const struct timeval zero = { 0, 0 }; 1772 1773 if (assign->dae != NULL) { 1774 if (assign->dae_reqpkt != NULL) 1775 TAILQ_REMOVE(&assign->dae->reqs, assign, dae_next); 1776 if (assign->dae_ntry > 0) { 1777 assign->dae->ninflight--; 1778 if (!evtimer_pending(&assign->dae->ev_reqs, NULL)) 1779 evtimer_add(&assign->dae->ev_reqs, &zero); 1780 } 1781 } 1782 if (assign->dae_reqpkt != NULL) 1783 radius_delete_packet(assign->dae_reqpkt); 1784 assign->dae_reqpkt = NULL; 1785 if (evtimer_pending(&assign->dae_evtimer, NULL)) 1786 evtimer_del(&assign->dae_evtimer); 1787 TAILQ_FOREACH_SAFE(client, &assign->dae_clients, entry, clientt) { 1788 TAILQ_REMOVE(&assign->dae_clients, client, entry); 1789 free(client); 1790 } 1791 assign->dae_ntry = 0; 1792 } 1793 1794 void 1795 ipcp_dae_send_pending_requests(int fd, short ev, void *ctx) 1796 { 1797 struct module_ipcp_dae *dae = ctx; 1798 struct module_ipcp *self = dae->ipcp; 1799 struct assigned_ipv4 *assign, *assignt; 1800 1801 ipcp_update_time(self); 1802 1803 TAILQ_FOREACH_SAFE(assign, &dae->reqs, dae_next, assignt) { 1804 if (dae->ninflight >= RADIUSD_IPCP_DAE_MAX_INFLIGHT) 1805 break; 1806 if (assign->dae_ntry == 0) /* pending */ 1807 ipcp_dae_send_disconnect_request(assign); 1808 } 1809 } 1810 1811 /*********************************************************************** 1812 * Miscellaneous functions 1813 ***********************************************************************/ 1814 struct ipcp_address * 1815 parse_address_range(const char *range) 1816 { 1817 char *buf, *sep; 1818 int masklen; 1819 uint32_t mask; 1820 struct in_addr start, end; 1821 struct ipcp_address *ret; 1822 const char *errstr; 1823 1824 buf = strdup(range); 1825 if (buf == NULL) 1826 goto error; 1827 if ((sep = strchr(buf, '-')) != NULL) { 1828 *sep = '\0'; 1829 if (inet_pton(AF_INET, buf, &start) != 1) 1830 goto error; 1831 else if (inet_pton(AF_INET, ++sep, &end) != 1) 1832 goto error; 1833 start.s_addr = ntohl(start.s_addr); 1834 end.s_addr = ntohl(end.s_addr); 1835 if (end.s_addr < start.s_addr) 1836 goto error; 1837 } else { 1838 if ((sep = strchr(buf, '/')) != NULL) { 1839 *sep = '\0'; 1840 if (inet_pton(AF_INET, buf, &start) != 1) 1841 goto error; 1842 masklen = strtonum(++sep, 0, 32, &errstr); 1843 if (errstr != NULL) 1844 goto error; 1845 } else { 1846 if (inet_pton(AF_INET, buf, &start) != 1) 1847 goto error; 1848 masklen = 32; 1849 } 1850 mask = 0xFFFFFFFFUL; 1851 if (masklen < 32) 1852 mask <<= (32 - masklen); 1853 start.s_addr = ntohl(start.s_addr) & mask; 1854 if (masklen == 32) 1855 end = start; 1856 else if (masklen == 31) 1857 end.s_addr = start.s_addr + 1; 1858 else { 1859 end.s_addr = start.s_addr + (1 << (32 - masklen)) - 2; 1860 start.s_addr = start.s_addr + 1; 1861 } 1862 } 1863 free(buf); 1864 if ((ret = calloc(1, sizeof(struct ipcp_address))) == NULL) 1865 return (NULL); 1866 ret->start = start; 1867 ret->end = end; 1868 ret->naddrs = end.s_addr - start.s_addr + 1; 1869 return (ret); 1870 error: 1871 free(buf); 1872 return (NULL); 1873 } 1874 1875 const char * 1876 radius_tunnel_type_string(unsigned val, const char *label) 1877 { 1878 unsigned int i; 1879 struct { 1880 const unsigned constval; 1881 const char *label; 1882 } tunnel_types[] = { 1883 { RADIUS_TUNNEL_TYPE_PPTP, "PPTP" }, 1884 { RADIUS_TUNNEL_TYPE_L2F, "L2F" }, 1885 { RADIUS_TUNNEL_TYPE_L2TP, "L2TP" }, 1886 { RADIUS_TUNNEL_TYPE_ATMP, "ATMP" }, 1887 { RADIUS_TUNNEL_TYPE_VTP, "VTP" }, 1888 { RADIUS_TUNNEL_TYPE_AH, "AH" }, 1889 { RADIUS_TUNNEL_TYPE_IP, "IP" }, 1890 { RADIUS_TUNNEL_TYPE_MOBILE, "MIN-IP-IP" }, 1891 { RADIUS_TUNNEL_TYPE_ESP, "ESP" }, 1892 { RADIUS_TUNNEL_TYPE_GRE, "GRE" }, 1893 { RADIUS_TUNNEL_TYPE_VDS, "DVS" }, 1894 /* [MS-RNAS] 3.3.5.1.9 Tunnel-Type */ 1895 { RADIUS_VENDOR_MICROSOFT << 8 | 1, 1896 "SSTP" } 1897 }; 1898 1899 if (label != NULL) { /* for conversion to the const value */ 1900 for (i = 0; i < nitems(tunnel_types); i++) { 1901 if (strcmp(tunnel_types[i].label, label) == 0) 1902 return (tunnel_types[i].label); 1903 } 1904 } 1905 1906 for (i = 0; i < nitems(tunnel_types); i++) { 1907 if (tunnel_types[i].constval == val) 1908 return (tunnel_types[i].label); 1909 } 1910 1911 return (NULL); 1912 } 1913 1914 const char * 1915 radius_terminate_cause_string(unsigned val) 1916 { 1917 unsigned int i; 1918 struct { 1919 const unsigned constval; 1920 const char *label; 1921 } terminate_causes[] = { 1922 { RADIUS_TERMNATE_CAUSE_USER_REQUEST, "User Request" }, 1923 { RADIUS_TERMNATE_CAUSE_LOST_CARRIER, "Lost Carrier" }, 1924 { RADIUS_TERMNATE_CAUSE_LOST_SERVICE, "Lost Service" }, 1925 { RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT, "Idle Timeout" }, 1926 { RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT, "Session Timeout" }, 1927 { RADIUS_TERMNATE_CAUSE_ADMIN_RESET, "Admin Reset" }, 1928 { RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT, "Admin Reboot" }, 1929 { RADIUS_TERMNATE_CAUSE_PORT_ERROR, "Port Error" }, 1930 { RADIUS_TERMNATE_CAUSE_NAS_ERROR, "NAS Error" }, 1931 { RADIUS_TERMNATE_CAUSE_NAS_RESET, "NAS Request" }, 1932 { RADIUS_TERMNATE_CAUSE_NAS_REBOOT, "NAS Reboot" }, 1933 { RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED, "Port Unneeded" }, 1934 { RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED, "Port Preempted" }, 1935 { RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED, "Port Suspended" }, 1936 { RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL, "Service Unavailable" }, 1937 { RADIUS_TERMNATE_CAUSE_CALLBACK, "Callback" }, 1938 { RADIUS_TERMNATE_CAUSE_USER_ERROR, "User Error" }, 1939 { RADIUS_TERMNATE_CAUSE_HOST_REQUEST, "Host Request" }, 1940 }; 1941 1942 for (i = 0; i < nitems(terminate_causes); i++) { 1943 if (terminate_causes[i].constval == val) 1944 return (terminate_causes[i].label); 1945 } 1946 1947 return (NULL); 1948 } 1949 1950 const char * 1951 radius_error_cause_string(unsigned val) 1952 { 1953 unsigned int i; 1954 struct { 1955 const unsigned constval; 1956 const char *label; 1957 } error_causes[] = { 1958 { RADIUS_ERROR_CAUSE_RESIDUAL_SESSION_REMOVED, 1959 "Residual Session Context Removed" }, 1960 { RADIUS_ERROR_CAUSE_INVALID_EAP_PACKET, 1961 "Invalid EAP Packet (Ignored)" }, 1962 { RADIUS_ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE, 1963 "Unsupported Attribute" }, 1964 { RADIUS_ERROR_CAUSE_MISSING_ATTRIBUTE, 1965 "Missing Attribute" }, 1966 { RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH, 1967 "NAS Identification Mismatch" }, 1968 { RADIUS_ERROR_CAUSE_INVALID_REQUEST, 1969 "Invalid Request" }, 1970 { RADIUS_ERROR_CAUSE_UNSUPPORTED_SERVICE, 1971 "Unsupported Service" }, 1972 { RADIUS_ERROR_CAUSE_UNSUPPORTED_EXTENSION, 1973 "Unsupported Extension" }, 1974 { RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE, 1975 "Invalid Attribute Value" }, 1976 { RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED, 1977 "Administratively Prohibited" }, 1978 { RADIUS_ERROR_CAUSE_REQUEST_NOT_ROUTABLE, 1979 "Request Not Routable (Proxy)" }, 1980 { RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND, 1981 "Session Context Not Found" }, 1982 { RADIUS_ERROR_CAUSE_SESSION_NOT_REMOVABLE, 1983 "Session Context Not Removable" }, 1984 { RADIUS_ERROR_CAUSE_OTHER_PROXY_PROCESSING_ERROR, 1985 "Other Proxy Processing Error" }, 1986 { RADIUS_ERROR_CAUSE_RESOURCES_UNAVAILABLE, 1987 "Resources Unavailable" }, 1988 { RADIUS_ERROR_CAUSE_REQUEST_INITIATED, 1989 "equest Initiated" }, 1990 { RADIUS_ERROR_CAUSE_MULTI_SELECTION_UNSUPPORTED, 1991 "Multiple Session Selection Unsupported" } 1992 }; 1993 1994 for (i = 0; i < nitems(error_causes); i++) { 1995 if (error_causes[i].constval == val) 1996 return (error_causes[i].label); 1997 } 1998 1999 return (NULL); 2000 } 2001 2002 int 2003 parse_addr(const char *str0, int af, struct sockaddr *sa, socklen_t salen) 2004 { 2005 int error; 2006 char *str, *end, *colon, *colon0, *addr = NULL, *port = NULL; 2007 char *sb, *sb0; 2008 struct addrinfo hints, *ai; 2009 2010 if ((str = strdup(str0)) == NULL) 2011 return (-1); 2012 if (*str == '[' && (end = strchr(str + 1, ']')) != NULL) { 2013 addr = str + 1; 2014 *end = '\0'; 2015 if (*(end + 1) == ':') 2016 port = end + 2; 2017 else if (*(end + 1) == '[' && (sb = strrchr(end + 2, ']')) 2018 != NULL) { 2019 port = end + 2; 2020 *sb = '\0'; 2021 } 2022 } else if ((sb0 = strchr(str, '[')) != NULL && 2023 (sb = strrchr(sb0 + 1, ']')) != NULL && sb0 < sb) { 2024 addr = str; 2025 *sb0 = '\0'; 2026 port = sb0 + 1; 2027 *sb = '\0'; 2028 } else if ((colon0 = strchr(str, ':')) != NULL && 2029 (colon = strrchr(str, ':')) != NULL && colon0 == colon) { 2030 /* has one : */ 2031 addr = str; 2032 *colon = '\0'; 2033 port = colon + 1; 2034 } else { 2035 addr = str; 2036 port = NULL; 2037 } 2038 2039 memset(&hints, 0, sizeof(hints)); 2040 hints.ai_family = af; 2041 hints.ai_socktype = SOCK_DGRAM; 2042 hints.ai_flags = AI_NUMERICHOST; 2043 if (port != NULL) 2044 hints.ai_flags |= AI_NUMERICSERV; 2045 if ((error = getaddrinfo(addr, port, &hints, &ai)) != 0) { 2046 free(str); 2047 return (-1); 2048 } 2049 free(str); 2050 if (salen < ai->ai_addrlen) { 2051 freeaddrinfo(ai); 2052 return (-1); 2053 } 2054 memcpy(sa, ai->ai_addr, ai->ai_addrlen); 2055 freeaddrinfo(ai); 2056 2057 return (0); 2058 } 2059 2060 const char * 2061 print_addr(struct sockaddr *sa, char *buf, size_t bufsiz) 2062 { 2063 int noport, ret; 2064 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 2065 2066 if (ntohs(((struct sockaddr_in *)sa)->sin_port) == 0) { 2067 noport = 1; 2068 ret = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 2069 NI_NUMERICHOST); 2070 } else { 2071 noport = 0; 2072 ret = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf, 2073 sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); 2074 } 2075 if (ret != 0) 2076 return ""; 2077 if (noport) 2078 strlcpy(buf, hbuf, bufsiz); 2079 else if (sa->sa_family == AF_INET6) 2080 snprintf(buf, bufsiz, "[%s]:%s", hbuf, sbuf); 2081 else 2082 snprintf(buf, bufsiz, "%s:%s", hbuf, sbuf); 2083 2084 return (buf); 2085 } 2086