1 /* $OpenBSD: radiusd_ipcp.c,v 1.21 2024/11/28 11:51:45 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 902 if (self->name_server[0].s_addr != 0) { 903 addr4.s_addr = htonl(self->name_server[0].s_addr); 904 radius_del_vs_attr_all(radres, 905 RADIUS_VENDOR_MICROSOFT, 906 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER); 907 radius_put_vs_ipv4_attr(radres, 908 RADIUS_VENDOR_MICROSOFT, 909 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, self->name_server[0]); 910 } 911 if (self->name_server[1].s_addr != 0) { 912 addr4.s_addr = htonl(self->name_server[1].s_addr); 913 radius_del_vs_attr_all(radres, 914 RADIUS_VENDOR_MICROSOFT, 915 RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER); 916 radius_put_vs_ipv4_attr(radres, 917 RADIUS_VENDOR_MICROSOFT, 918 RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER, self->name_server[1]); 919 } 920 if (self->netbios_server[0].s_addr != 0) { 921 addr4.s_addr = htonl(self->netbios_server[0].s_addr); 922 radius_del_vs_attr_all(radres, 923 RADIUS_VENDOR_MICROSOFT, 924 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER); 925 radius_put_vs_ipv4_attr(radres, 926 RADIUS_VENDOR_MICROSOFT, 927 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, 928 self->netbios_server[0]); 929 } 930 if (self->netbios_server[1].s_addr != 0) { 931 addr4.s_addr = htonl(self->netbios_server[1].s_addr); 932 radius_del_vs_attr_all(radres, 933 RADIUS_VENDOR_MICROSOFT, 934 RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER); 935 radius_put_vs_ipv4_attr(radres, 936 RADIUS_VENDOR_MICROSOFT, 937 RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER, 938 self->netbios_server[1]); 939 } 940 if (!self->no_session_timeout && 941 radius_has_attr(radres, RADIUS_TYPE_SESSION_TIMEOUT)) { 942 radius_get_uint32_attr(radres, RADIUS_TYPE_SESSION_TIMEOUT, 943 &assigned->session_timeout); 944 /* we handle this session-timeout */ 945 radius_del_attr_all(radres, RADIUS_TYPE_SESSION_TIMEOUT); 946 } 947 948 accept: 949 if (module_resdeco_done(self->base, q_id, radius_get_data(radres), 950 radius_get_length(radres)) == -1) { 951 log_warn("%s: module_resdeco_done() failed", __func__); 952 module_stop(self->base); 953 } 954 if (radreq != NULL) 955 radius_delete_packet(radreq); 956 radius_delete_packet(radres); 957 return; 958 reject: 959 ipcp_reject(self, radreq, q_id, radres, msraserr); 960 radius_delete_packet(radreq); 961 radius_delete_packet(radres); 962 return; 963 fatal: 964 if (radreq != NULL) 965 radius_delete_packet(radreq); 966 if (radres != NULL) 967 radius_delete_packet(radres); 968 module_stop(self->base); 969 } 970 971 void 972 ipcp_reject(struct module_ipcp *self, RADIUS_PACKET *reqp, unsigned int q_id, 973 RADIUS_PACKET *orig_resp, int mserr) 974 { 975 bool is_eap, is_mschap, is_mschap2; 976 uint8_t attr[256]; 977 size_t attrlen; 978 RADIUS_PACKET *resp; 979 struct { 980 uint8_t code; 981 uint8_t id; 982 uint16_t length; 983 } __packed eap; 984 985 resp = radius_new_response_packet(RADIUS_CODE_ACCESS_REJECT, reqp); 986 if (resp == NULL) { 987 log_warn("%s: radius_new_response_packet() failed", __func__); 988 module_accsreq_aborted(self->base, q_id); 989 return; 990 } 991 992 is_eap = radius_has_attr(reqp, RADIUS_TYPE_EAP_MESSAGE); 993 if (radius_get_vs_raw_attr(reqp, RADIUS_VENDOR_MICROSOFT, 994 RADIUS_VTYPE_MS_CHAP_RESPONSE, attr, &attrlen) == 0) 995 is_mschap = true; 996 else if (radius_get_vs_raw_attr(reqp, RADIUS_VENDOR_MICROSOFT, 997 RADIUS_VTYPE_MS_CHAP2_RESPONSE, attr, &attrlen) == 0) 998 is_mschap2 = true; 999 1000 if (is_eap) { 1001 memset(&eap, 0, sizeof(eap)); /* just in case */ 1002 eap.code = 1; /* EAP Request */ 1003 attrlen = sizeof(attr); 1004 if (orig_resp != NULL && radius_get_raw_attr(orig_resp, 1005 RADIUS_TYPE_EAP_MESSAGE, &attr, &attrlen) == 0) 1006 eap.id = attr[1]; 1007 else 1008 eap.id = 0; 1009 eap.length = htons(sizeof(eap)); 1010 radius_put_raw_attr(resp, RADIUS_TYPE_EAP_MESSAGE, &eap, 1011 ntohs(eap.length)); 1012 } else if (is_mschap || is_mschap2) { 1013 attr[0] = attr[1]; /* Copy the ident of the request */ 1014 snprintf(attr + 1, sizeof(attr) - 1, "E=%d R=0 V=3", mserr); 1015 radius_put_vs_raw_attr(resp, RADIUS_VENDOR_MICROSOFT, 1016 RADIUS_VTYPE_MS_CHAP_ERROR, attr, strlen(attr + 1) + 1); 1017 } 1018 1019 module_resdeco_done(self->base, q_id, radius_get_data(resp), 1020 radius_get_length(resp)); 1021 radius_delete_packet(resp); 1022 } 1023 1024 /*********************************************************************** 1025 * RADIUS Accounting 1026 ***********************************************************************/ 1027 void 1028 ipcp_accounting_request(void *ctx, u_int q_id, const u_char *pkt, 1029 size_t pktlen) 1030 { 1031 RADIUS_PACKET *radpkt = NULL; 1032 int code, af; 1033 uint32_t type, delay, uval; 1034 struct in_addr addr4, nas_ipv4; 1035 struct in6_addr nas_ipv6, ipv6_zero; 1036 struct module_ipcp *self = ctx; 1037 struct assigned_ipv4 *assign, *assignt; 1038 char username[256], nas_id[256], buf[256], 1039 buf1[384]; 1040 struct timespec dur; 1041 struct radiusd_ipcp_statistics 1042 stat; 1043 struct module_ipcp_dae *dae; 1044 1045 ipcp_update_time(self); 1046 1047 if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) { 1048 log_warn("%s: radius_convert_packet() failed", __func__); 1049 module_stop(self->base); 1050 return; 1051 } 1052 code = radius_get_code(radpkt); 1053 if (code != RADIUS_CODE_ACCOUNTING_REQUEST && 1054 code != RADIUS_CODE_ACCOUNTING_RESPONSE) 1055 goto out; 1056 1057 if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_STATUS_TYPE, &type) 1058 != 0) 1059 goto out; 1060 1061 /* identifier for the NAS */ 1062 memset(&ipv6_zero, 0, sizeof(ipv6_zero)); 1063 memset(&nas_ipv4, 0, sizeof(nas_ipv4)); 1064 memset(&nas_ipv6, 0, sizeof(nas_ipv6)); 1065 memset(&nas_id, 0, sizeof(nas_id)); 1066 1067 radius_get_ipv4_attr(radpkt, RADIUS_TYPE_NAS_IP_ADDRESS, &nas_ipv4); 1068 radius_get_ipv6_attr(radpkt, RADIUS_TYPE_NAS_IPV6_ADDRESS, &nas_ipv6); 1069 radius_get_string_attr(radpkt, RADIUS_TYPE_NAS_IDENTIFIER, nas_id, 1070 sizeof(nas_id)); 1071 1072 if (nas_ipv4.s_addr == 0 && IN6_ARE_ADDR_EQUAL(&nas_ipv6, &ipv6_zero) && 1073 nas_id[0] == '\0') { 1074 log_warnx("q=%u no NAS-IP-Address, NAS-IPV6-Address, or " 1075 "NAS-Identifier", q_id); 1076 goto out; 1077 } 1078 1079 if (type == RADIUS_ACCT_STATUS_TYPE_ACCT_ON || 1080 type == RADIUS_ACCT_STATUS_TYPE_ACCT_OFF) { 1081 /* 1082 * NAS or daemon is restarted. Delete all assigned records 1083 * from it 1084 */ 1085 RB_FOREACH_SAFE(assign, assigned_ipv4_tree, &self->ipv4s, 1086 assignt) { 1087 if (assign->nas_ipv4.s_addr != nas_ipv4.s_addr || 1088 !IN6_ARE_ADDR_EQUAL(&assign->nas_ipv6, &nas_ipv6) || 1089 strcmp(assign->nas_id, nas_id) != 0) 1090 continue; 1091 log_info("q=%u Delete record for %s", q_id, 1092 inet_ntop(AF_INET, &assign->ipv4, buf, 1093 sizeof(buf))); 1094 ipcp_ipv4_delete(self, assign, 1095 (type == RADIUS_ACCT_STATUS_TYPE_ACCT_ON) 1096 ? "Receive Acct-On" : "Receive Acct-Off"); 1097 } 1098 return; 1099 } 1100 1101 if (radius_get_ipv4_attr(radpkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, &addr4) 1102 != 0) { 1103 log_warnx("q=%u no Framed-IP-Address-Address attribute", q_id); 1104 goto out; 1105 } 1106 if (radius_get_string_attr(radpkt, RADIUS_TYPE_USER_NAME, username, 1107 sizeof(username)) != 0) { 1108 log_warnx("q=%u no User-Name attribute", q_id); 1109 goto out; 1110 } 1111 if ((assign = ipcp_ipv4_find(self, addr4)) == NULL) { 1112 /* not assigned by this */ 1113 log_warnx("q=%u %s is not assigned by us", q_id, 1114 inet_ntop(AF_INET, &addr4, buf, sizeof(buf))); 1115 goto out; 1116 } 1117 1118 if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_DELAY_TIME, &delay) 1119 != 0) 1120 delay = 0; 1121 1122 if (type == RADIUS_ACCT_STATUS_TYPE_START) { 1123 assign->start = self->uptime; 1124 assign->start.tv_sec -= delay; 1125 1126 if (!self->no_session_timeout && (self->session_timeout > 0 || 1127 assign->session_timeout > 0)) { 1128 assign->timeout = assign->start; 1129 if (self->session_timeout > 0) 1130 assign->timeout.tv_sec += self->session_timeout; 1131 else 1132 assign->timeout.tv_sec += 1133 assign->session_timeout; 1134 } 1135 assign->nas_ipv4 = nas_ipv4; 1136 assign->nas_ipv6 = nas_ipv6; 1137 strlcpy(assign->nas_id, nas_id, sizeof(assign->nas_id)); 1138 1139 if (radius_get_string_attr(radpkt, RADIUS_TYPE_ACCT_SESSION_ID, 1140 assign->session_id, sizeof(assign->session_id)) != 0) 1141 assign->session_id[0] = '\0'; 1142 if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_TUNNEL_TYPE, 1143 &uval) == 0) 1144 assign->tun_type = radius_tunnel_type_string(uval, 1145 NULL); 1146 if (assign->tun_type == NULL) 1147 assign->tun_type = ""; 1148 1149 /* 1150 * Get "tunnel from" from Tunnel-Client-Endpoint or Calling- 1151 * Station-Id 1152 */ 1153 af = AF_UNSPEC; 1154 if (radius_get_string_attr(radpkt, 1155 RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT, buf, sizeof(buf)) == 0) 1156 { 1157 if (radius_get_uint32_attr(radpkt, 1158 RADIUS_TYPE_TUNNEL_MEDIUM_TYPE, &uval) == 0) { 1159 if (uval == RADIUS_TUNNEL_MEDIUM_TYPE_IPV4) 1160 af = AF_INET; 1161 else if (uval == RADIUS_TUNNEL_MEDIUM_TYPE_IPV6) 1162 af = AF_INET6; 1163 } 1164 parse_addr(buf, af, (struct sockaddr *) 1165 &assign->tun_client, sizeof(assign->tun_client)); 1166 } 1167 if (assign->tun_client.sin4.sin_family == 0 && 1168 radius_get_string_attr(radpkt, 1169 RADIUS_TYPE_CALLING_STATION_ID, buf, sizeof(buf)) == 0) 1170 parse_addr(buf, af, (struct sockaddr *) 1171 &assign->tun_client, sizeof(assign->tun_client)); 1172 1173 TAILQ_FOREACH(dae, &self->daes, next) { 1174 if (dae->nas_id[0] == '\0' || 1175 strcmp(dae->nas_id, assign->nas_id) == 0) 1176 break; 1177 } 1178 assign->dae = dae; 1179 1180 ipcp_put_db(self, assign); 1181 ipcp_schedule_timer(self); 1182 1183 if (ipcp_notice_startstop(self, assign, 1, NULL) != 0) 1184 goto fail; 1185 log_info("q=%u Start seq=%u user=%s duration=%dsec " 1186 "session=%s tunnel=%s from=%s auth=%s ip=%s", q_id, 1187 assign->seq, assign->user->name, delay, assign->session_id, 1188 assign->tun_type, print_addr((struct sockaddr *) 1189 &assign->tun_client, buf1, sizeof(buf1)), 1190 assign->auth_method, inet_ntop(AF_INET, &addr4, buf, 1191 sizeof(buf))); 1192 } else if (type == RADIUS_ACCT_STATUS_TYPE_STOP) { 1193 memset(&stat, 0, sizeof(stat)); 1194 1195 dur = self->uptime; 1196 dur.tv_sec -= delay; 1197 timespecsub(&dur, &assign->start, &dur); 1198 1199 if (radius_get_uint32_attr(radpkt, 1200 RADIUS_TYPE_ACCT_INPUT_OCTETS, &uval) == 0) 1201 stat.ibytes = uval; 1202 if (radius_get_uint32_attr(radpkt, 1203 RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, &uval) == 0) 1204 stat.ibytes = ((uint64_t)uval << 32) | stat.ibytes; 1205 if (radius_get_uint32_attr(radpkt, 1206 RADIUS_TYPE_ACCT_OUTPUT_OCTETS, &uval) == 0) 1207 stat.obytes = uval; 1208 if (radius_get_uint32_attr(radpkt, 1209 RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS, &uval) == 0) 1210 stat.obytes = ((uint64_t)uval << 32) | stat.obytes; 1211 radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_INPUT_PACKETS, 1212 &stat.ipackets); 1213 radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS, 1214 &stat.opackets); 1215 1216 if (radius_get_uint32_attr(radpkt, 1217 RADIUS_TYPE_ACCT_TERMINATE_CAUSE, &uval) == 0) 1218 strlcpy(stat.cause, radius_terminate_cause_string(uval), 1219 sizeof(stat.cause)); 1220 1221 log_info("q=%u Stop seq=%u user=%s duration=%lldsec " 1222 "session=%s tunnel=%s from=%s auth=%s ip=%s " 1223 "datain=%"PRIu64"bytes,%" PRIu32"packets dataout=%"PRIu64 1224 "bytes,%"PRIu32"packets cause=\"%s\"", q_id, 1225 assign->seq, assign->user->name, dur.tv_sec, 1226 assign->session_id, assign->tun_type, print_addr( 1227 (struct sockaddr *)&assign->tun_client, buf1, sizeof(buf1)), 1228 assign->auth_method, inet_ntop(AF_INET, &addr4, buf, 1229 sizeof(buf)), stat.ibytes, stat.ipackets, stat.obytes, 1230 stat.opackets, stat.cause); 1231 1232 ipcp_del_db(self, assign); 1233 if (ipcp_notice_startstop(self, assign, 0, &stat) != 0) 1234 goto fail; 1235 ipcp_ipv4_release(self, ipcp_ipv4_find(self, addr4)); 1236 } 1237 out: 1238 radius_delete_packet(radpkt); 1239 return; 1240 fail: 1241 module_stop(self->base); 1242 radius_delete_packet(radpkt); 1243 return; 1244 } 1245 1246 /*********************************************************************** 1247 * On memory database to manage IP address assignment 1248 ***********************************************************************/ 1249 struct assigned_ipv4 * 1250 ipcp_ipv4_assign(struct module_ipcp *self, struct user *user, 1251 struct in_addr ina) 1252 { 1253 struct assigned_ipv4 *ip; 1254 1255 ip = calloc(1, sizeof(struct assigned_ipv4)); 1256 if (ip == NULL) { 1257 log_warn("%s: calloc()", __func__); 1258 return (NULL); 1259 } 1260 ip->ipv4 = ina; 1261 ip->user = user; 1262 ip->authtime = self->uptime; 1263 RB_INSERT(assigned_ipv4_tree, &self->ipv4s, ip); 1264 TAILQ_INSERT_TAIL(&user->ipv4s, ip, next); 1265 TAILQ_INIT(&ip->dae_clients); 1266 self->nsessions++; 1267 ip->seq = self->seq++; 1268 1269 return (ip); 1270 } 1271 1272 struct assigned_ipv4 * 1273 ipcp_ipv4_find(struct module_ipcp *self, struct in_addr ina) 1274 { 1275 struct assigned_ipv4 key, *ret; 1276 struct timespec dif; 1277 1278 key.ipv4 = ina; 1279 ret = RB_FIND(assigned_ipv4_tree, &self->ipv4s, &key); 1280 if (ret != NULL && ret->start.tv_sec == 0) { 1281 /* not yet assigned */ 1282 timespecsub(&self->uptime, &ret->authtime, &dif); 1283 if (dif.tv_sec >= self->start_wait) { 1284 /* assumed NAS finally didn't use the address */ 1285 TAILQ_REMOVE(&ret->user->ipv4s, ret, next); 1286 RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, ret); 1287 free(ret); 1288 ret = NULL; 1289 self->nsessions--; 1290 } 1291 } 1292 return (ret); 1293 } 1294 1295 void 1296 ipcp_ipv4_delete(struct module_ipcp *self, struct assigned_ipv4 *assign, 1297 const char *cause) 1298 { 1299 struct radiusd_ipcp_statistics stat; 1300 1301 memset(&stat, 0, sizeof(stat)); 1302 strlcpy(stat.cause, cause, sizeof(stat.cause)); 1303 1304 ipcp_del_db(self, assign); 1305 ipcp_notice_startstop(self, assign, 0, &stat); 1306 ipcp_ipv4_release(self, assign); 1307 } 1308 1309 void 1310 ipcp_ipv4_release(struct module_ipcp *self, struct assigned_ipv4 *assign) 1311 { 1312 if (assign != NULL) { 1313 TAILQ_REMOVE(&assign->user->ipv4s, assign, next); 1314 RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, assign); 1315 self->nsessions--; 1316 ipcp_dae_reset_request(assign); 1317 free(assign); 1318 } 1319 } 1320 1321 int 1322 assigned_ipv4_compar(struct assigned_ipv4 *a, struct assigned_ipv4 *b) 1323 { 1324 if (a->ipv4.s_addr > b->ipv4.s_addr) 1325 return (1); 1326 else if (a->ipv4.s_addr < b->ipv4.s_addr) 1327 return (-1); 1328 return (0); 1329 } 1330 1331 struct user * 1332 ipcp_user_get(struct module_ipcp *self, const char *username) 1333 { 1334 struct { 1335 struct user user; 1336 char name[256]; 1337 } key; 1338 struct user *elm; 1339 1340 strlcpy(key.user.name, username, 256); 1341 elm = RB_FIND(user_tree, &self->users, &key.user); 1342 if (elm == NULL) { 1343 if ((elm = calloc(1, offsetof(struct user, name[ 1344 strlen(username) + 1]))) == NULL) 1345 return (NULL); 1346 memcpy(elm->name, username, strlen(username)); 1347 RB_INSERT(user_tree, &self->users, elm); 1348 TAILQ_INIT(&elm->ipv4s); 1349 } 1350 1351 return (elm); 1352 } 1353 1354 int 1355 user_compar(struct user *a, struct user *b) 1356 { 1357 return (strcmp(a->name, b->name)); 1358 } 1359 1360 RB_GENERATE_STATIC(assigned_ipv4_tree, assigned_ipv4, tree, 1361 assigned_ipv4_compar); 1362 RB_GENERATE_STATIC(user_tree, user, tree, user_compar); 1363 1364 /*********************************************************************** 1365 * DB for the persistent over processes 1366 ***********************************************************************/ 1367 int 1368 ipcp_prepare_db(void) 1369 { 1370 struct passwd *pw; 1371 DB *db; 1372 1373 if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_CREAT | O_RDWR | O_EXLOCK, 1374 0600, DB_BTREE, NULL)) == NULL) 1375 return (-1); 1376 if ((pw = getpwnam(RADIUSD_USER)) == NULL) 1377 return (-1); 1378 fchown(db->fd(db), pw->pw_uid, pw->pw_gid); 1379 db->close(db); 1380 1381 return (0); 1382 } 1383 1384 int 1385 ipcp_restore_from_db(struct module_ipcp *self) 1386 { 1387 DB *db; 1388 DBT key, val; 1389 char keybuf[128]; 1390 struct user *user; 1391 struct radiusd_ipcp_db_record 1392 *record; 1393 struct assigned_ipv4 *assigned; 1394 struct in_addr ipv4; 1395 struct module_ipcp_dae *dae; 1396 1397 if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDONLY | O_SHLOCK, 0600, 1398 DB_BTREE, NULL)) == NULL) 1399 return (-1); 1400 1401 key.data = "ipv4/"; 1402 key.size = 5; 1403 if (db->seq(db, &key, &val, R_CURSOR) == 0) { 1404 do { 1405 if (key.size >= sizeof(keybuf)) 1406 break; 1407 memcpy(keybuf, key.data, key.size); 1408 keybuf[key.size] = '\0'; 1409 if (strncmp(keybuf, "ipv4/", 5) != 0) 1410 break; 1411 inet_pton(AF_INET, keybuf + 5, &ipv4); 1412 record = (struct radiusd_ipcp_db_record *)val.data; 1413 if ((user = ipcp_user_get(self, record->username)) 1414 == NULL) 1415 return (-1); 1416 if ((assigned = ipcp_ipv4_assign(self, user, ipv4)) 1417 == NULL) 1418 return (-1); 1419 assigned->seq = record->seq; 1420 self->seq = MAXIMUM(assigned->seq + 1, self->seq); 1421 strlcpy(assigned->auth_method, record->auth_method, 1422 sizeof(assigned->auth_method)); 1423 strlcpy(assigned->session_id, record->session_id, 1424 sizeof(assigned->session_id)); 1425 assigned->start = record->start; 1426 assigned->timeout = record->timeout; 1427 assigned->nas_ipv4 = record->nas_ipv4; 1428 assigned->nas_ipv6 = record->nas_ipv6; 1429 strlcpy(assigned->nas_id, record->nas_id, 1430 sizeof(assigned->nas_id)); 1431 assigned->tun_type = radius_tunnel_type_string(0, 1432 record->tun_type); 1433 memcpy(&assigned->tun_client, &record->tun_client, 1434 sizeof(assigned->tun_client)); 1435 1436 TAILQ_FOREACH(dae, &self->daes, next) { 1437 if (dae->nas_id[0] == '\0' || 1438 strcmp(dae->nas_id, assigned->nas_id) == 0) 1439 break; 1440 } 1441 assigned->dae = dae; 1442 } while (db->seq(db, &key, &val, R_NEXT) == 0); 1443 } 1444 db->close(db); 1445 1446 return (0); 1447 } 1448 1449 void 1450 ipcp_put_db(struct module_ipcp *self, struct assigned_ipv4 *assigned) 1451 { 1452 DB *db; 1453 DBT key, val; 1454 char keybuf[128]; 1455 struct radiusd_ipcp_db_record 1456 record; 1457 1458 strlcpy(keybuf, "ipv4/", sizeof(keybuf)); 1459 inet_ntop(AF_INET, &assigned->ipv4, keybuf + 5, sizeof(keybuf) - 5); 1460 key.data = keybuf; 1461 key.size = strlen(keybuf); 1462 strlcpy(record.session_id, assigned->session_id, 1463 sizeof(record.session_id)); 1464 strlcpy(record.auth_method, assigned->auth_method, 1465 sizeof(record.auth_method)); 1466 strlcpy(record.username, assigned->user->name, sizeof(record.username)); 1467 record.seq = assigned->seq; 1468 record.start = assigned->start; 1469 record.timeout = assigned->timeout; 1470 record.nas_ipv4 = assigned->nas_ipv4; 1471 record.nas_ipv6 = assigned->nas_ipv6; 1472 strlcpy(record.nas_id, assigned->nas_id, sizeof(record.nas_id)); 1473 if (assigned->tun_type != NULL) 1474 strlcpy(record.tun_type, assigned->tun_type, 1475 sizeof(record.tun_type)); 1476 memcpy(&record.tun_client, &assigned->tun_client, 1477 sizeof(record.tun_client)); 1478 1479 val.data = &record; 1480 val.size = sizeof(record); 1481 if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDWR | O_EXLOCK, 0600, 1482 DB_BTREE, NULL)) == NULL) 1483 return; 1484 db->put(db, &key, &val, 0); 1485 db->close(db); 1486 } 1487 1488 void 1489 ipcp_del_db(struct module_ipcp *self, struct assigned_ipv4 *assigned) 1490 { 1491 DB *db; 1492 DBT key; 1493 char keybuf[128]; 1494 1495 strlcpy(keybuf, "ipv4/", sizeof(keybuf)); 1496 inet_ntop(AF_INET, &assigned->ipv4, keybuf + 5, sizeof(keybuf) - 5); 1497 key.data = keybuf; 1498 key.size = strlen(keybuf); 1499 1500 if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDWR | O_EXLOCK, 0600, 1501 DB_BTREE, NULL)) == NULL) 1502 return; 1503 db->del(db, &key, 0); 1504 db->close(db); 1505 } 1506 1507 void 1508 ipcp_db_dump_fill_record(struct radiusd_ipcp_db_dump *dump, int idx, 1509 struct assigned_ipv4 *assign) 1510 { 1511 dump->records[idx].af = AF_INET; 1512 dump->records[idx].addr.ipv4 = assign->ipv4; 1513 dump->records[idx].rec.seq = assign->seq; 1514 strlcpy(dump->records[idx].rec.session_id, assign->session_id, 1515 sizeof(dump->records[idx].rec.session_id)); 1516 strlcpy(dump->records[idx].rec.auth_method, assign->auth_method, 1517 sizeof(dump->records[idx].rec.auth_method)); 1518 strlcpy(dump->records[idx].rec.username, assign->user->name, 1519 sizeof(dump->records[idx].rec.username)); 1520 dump->records[idx].rec.start = assign->start; 1521 dump->records[idx].rec.timeout = assign->timeout; 1522 dump->records[idx].rec.nas_ipv4 = assign->nas_ipv4; 1523 dump->records[idx].rec.nas_ipv6 = assign->nas_ipv6; 1524 strlcpy(dump->records[idx].rec.nas_id, assign->nas_id, 1525 sizeof(dump->records[idx].rec.nas_id)); 1526 if (assign->tun_type != NULL) 1527 strlcpy(dump->records[idx].rec.tun_type, assign->tun_type, 1528 sizeof(dump->records[idx].rec.tun_type)); 1529 memcpy(&dump->records[idx].rec.tun_client, &assign->tun_client, 1530 sizeof(dump->records[idx].rec.tun_client)); 1531 } 1532 1533 /*********************************************************************** 1534 * Timer 1535 ***********************************************************************/ 1536 void 1537 ipcp_update_time(struct module_ipcp *self) 1538 { 1539 clock_gettime(CLOCK_BOOTTIME, &self->uptime); 1540 } 1541 1542 void 1543 ipcp_on_timer(int fd, short ev, void *ctx) 1544 { 1545 struct module_ipcp *self = ctx; 1546 1547 ipcp_update_time(self); 1548 ipcp_schedule_timer(self); 1549 } 1550 1551 void 1552 ipcp_schedule_timer(struct module_ipcp *self) 1553 { 1554 struct assigned_ipv4 *assign, *min_assign = NULL; 1555 struct timespec tsd; 1556 struct timeval tv; 1557 1558 /* check session timeout */ 1559 RB_FOREACH(assign, assigned_ipv4_tree, &self->ipv4s) { 1560 if (assign->timeout.tv_sec == 0) 1561 continue; 1562 if (timespeccmp(&assign->timeout, &self->uptime, <=)) { 1563 log_info("Reached session timeout seq=%u", assign->seq); 1564 ipcp_dae_send_disconnect_request(assign); 1565 memset(&assign->timeout, 0, sizeof(assign->timeout)); 1566 ipcp_put_db(self, assign); 1567 } 1568 if (min_assign == NULL || 1569 timespeccmp(&min_assign->timeout, &assign->timeout, >)) 1570 min_assign = assign; 1571 } 1572 if (evtimer_pending(&self->ev_timer, NULL)) 1573 evtimer_del(&self->ev_timer); 1574 1575 if (min_assign != NULL) { 1576 timespecsub(&min_assign->timeout, &self->uptime, &tsd); 1577 TIMESPEC_TO_TIMEVAL(&tv, &tsd); 1578 evtimer_set(&self->ev_timer, ipcp_on_timer, self); 1579 evtimer_add(&self->ev_timer, &tv); 1580 } 1581 } 1582 1583 /*********************************************************************** 1584 * Dynamic Authorization Extension for RAIDUS (RFC 5176) 1585 ***********************************************************************/ 1586 static const int dae_request_timeouts[] = { 2, 4, 8, 8 }; 1587 1588 void 1589 ipcp_dae_send_disconnect_request(struct assigned_ipv4 *assign) 1590 { 1591 RADIUS_PACKET *reqpkt = NULL; 1592 struct timeval tv; 1593 char buf[80]; 1594 1595 if (assign->dae == NULL) 1596 return; /* DAE is not configured */ 1597 1598 if (assign->dae_reqpkt == NULL) { 1599 if ((reqpkt = radius_new_request_packet( 1600 RADIUS_CODE_DISCONNECT_REQUEST)) == NULL) { 1601 log_warn("%s: radius_new_request_packet(): %m", 1602 __func__); 1603 return; 1604 } 1605 radius_put_string_attr(reqpkt, RADIUS_TYPE_ACCT_SESSION_ID, 1606 assign->session_id); 1607 /* 1608 * RFC 5176 Section 3, "either the User-Name or 1609 * Chargeable-User-Identity attribute SHOULD be present in 1610 * Disconnect-Request and CoA-Request packets." 1611 */ 1612 radius_put_string_attr(reqpkt, RADIUS_TYPE_USER_NAME, 1613 assign->user->name); 1614 if (assign->nas_id[0] != '\0') 1615 radius_put_string_attr(reqpkt, 1616 RADIUS_TYPE_NAS_IDENTIFIER, assign->nas_id); 1617 if (ntohl(assign->nas_ipv4.s_addr) != 0) 1618 radius_put_ipv4_attr(reqpkt, 1619 RADIUS_TYPE_NAS_IP_ADDRESS, assign->nas_ipv4); 1620 if (!IN6_IS_ADDR_UNSPECIFIED(&assign->nas_ipv6)) 1621 radius_put_ipv6_attr(reqpkt, 1622 RADIUS_TYPE_NAS_IPV6_ADDRESS, &assign->nas_ipv6); 1623 radius_set_accounting_request_authenticator(reqpkt, 1624 assign->dae->secret); 1625 assign->dae_reqpkt = reqpkt; 1626 TAILQ_INSERT_TAIL(&assign->dae->reqs, assign, dae_next); 1627 } 1628 1629 if (assign->dae_ntry == 0) { 1630 if (assign->dae->ninflight >= RADIUSD_IPCP_DAE_MAX_INFLIGHT) 1631 return; 1632 log_info("Sending Disconnect-Request seq=%u to %s", 1633 assign->seq, print_addr((struct sockaddr *) 1634 &assign->dae->nas_addr, buf, sizeof(buf))); 1635 } 1636 1637 if (radius_send(assign->dae->sock, assign->dae_reqpkt, 0) < 0) 1638 log_warn("%s: sendto: %m", __func__); 1639 1640 tv.tv_sec = dae_request_timeouts[assign->dae_ntry]; 1641 tv.tv_usec = 0; 1642 evtimer_set(&assign->dae_evtimer, ipcp_dae_request_on_timeout, assign); 1643 evtimer_add(&assign->dae_evtimer, &tv); 1644 if (assign->dae_ntry == 0) 1645 assign->dae->ninflight++; 1646 assign->dae_ntry++; 1647 } 1648 1649 void 1650 ipcp_dae_request_on_timeout(int fd, short ev, void *ctx) 1651 { 1652 struct assigned_ipv4 *assign = ctx; 1653 char buf[80]; 1654 struct radiusctl_client *client; 1655 1656 if (assign->dae_ntry >= (int)nitems(dae_request_timeouts)) { 1657 log_warnx("No answer for Disconnect-Request seq=%u from %s", 1658 assign->seq, print_addr((struct sockaddr *) 1659 &assign->dae->nas_addr, buf, sizeof(buf))); 1660 TAILQ_FOREACH(client, &assign->dae_clients, entry) 1661 module_imsg_compose(assign->dae->ipcp->base, IMSG_NG, 1662 client->peerid, 0, -1, NULL, 0); 1663 ipcp_dae_reset_request(assign); 1664 } else 1665 ipcp_dae_send_disconnect_request(assign); 1666 } 1667 1668 void 1669 ipcp_dae_on_event(int fd, short ev, void *ctx) 1670 { 1671 struct module_ipcp_dae *dae = ctx; 1672 struct module_ipcp *self = dae->ipcp; 1673 RADIUS_PACKET *radres = NULL; 1674 int code; 1675 uint32_t u32; 1676 struct assigned_ipv4 *assign; 1677 char buf[80], causestr[80]; 1678 const char *cause = ""; 1679 struct radiusctl_client *client; 1680 1681 ipcp_update_time(self); 1682 1683 if ((ev & EV_READ) == 0) 1684 return; 1685 1686 if ((radres = radius_recv(dae->sock, 0)) == NULL) { 1687 if (errno == EAGAIN) 1688 return; 1689 log_warn("%s: Failed to receive from %s", __func__, print_addr( 1690 (struct sockaddr *)&dae->nas_addr, buf, sizeof(buf))); 1691 return; 1692 } 1693 TAILQ_FOREACH(assign, &dae->reqs, dae_next) { 1694 if (radius_get_id(assign->dae_reqpkt) == radius_get_id(radres)) 1695 break; 1696 } 1697 if (assign == NULL) { 1698 log_warnx("%s: Received RADIUS packet from %s has unknown " 1699 "id=%d", __func__, print_addr((struct sockaddr *) 1700 &dae->nas_addr, buf, sizeof(buf)), radius_get_id(radres)); 1701 goto out; 1702 } 1703 1704 radius_set_request_packet(radres, assign->dae_reqpkt); 1705 if ((radius_check_response_authenticator(radres, dae->secret)) != 0) { 1706 log_warnx("%s: Received RADIUS packet for seq=%u from %s has " 1707 "a bad authenticator", __func__, assign->seq, print_addr( 1708 (struct sockaddr *)&dae->nas_addr, buf, 1709 sizeof(buf))); 1710 goto out; 1711 } 1712 causestr[0] = '\0'; 1713 if (radius_get_uint32_attr(radres, RADIUS_TYPE_ERROR_CAUSE, &u32) == 0){ 1714 cause = radius_error_cause_string(u32); 1715 if (cause != NULL) 1716 snprintf(causestr, sizeof(causestr), " cause=%u(%s)", 1717 u32, cause); 1718 else 1719 snprintf(causestr, sizeof(causestr), " cause=%u", u32); 1720 cause = causestr; 1721 } 1722 1723 code = radius_get_code(radres); 1724 switch (code) { 1725 case RADIUS_CODE_DISCONNECT_ACK: 1726 log_info("Received Disconnect-ACK for seq=%u from %s%s", 1727 assign->seq, print_addr((struct sockaddr *) 1728 &dae->nas_addr, buf, sizeof(buf)), cause); 1729 break; 1730 case RADIUS_CODE_DISCONNECT_NAK: 1731 log_info("Received Disconnect-NAK for seq=%u from %s%s", 1732 assign->seq, print_addr((struct sockaddr *) 1733 &dae->nas_addr, buf, sizeof(buf)), cause); 1734 break; 1735 default: 1736 log_warn("%s: Received unknown code=%d for id=%u from %s", 1737 __func__, code, assign->seq, print_addr((struct sockaddr *) 1738 &dae->nas_addr, buf, sizeof(buf))); 1739 break; 1740 } 1741 1742 TAILQ_FOREACH(client, &assign->dae_clients, entry) { 1743 if (*cause != '\0') 1744 module_imsg_compose(self->base, 1745 (code == RADIUS_CODE_DISCONNECT_ACK) 1746 ? IMSG_OK : IMSG_NG, client->peerid, 0, -1, 1747 cause + 1, strlen(cause + 1) + 1); 1748 else 1749 module_imsg_compose(self->base, 1750 (code == RADIUS_CODE_DISCONNECT_ACK) 1751 ? IMSG_OK : IMSG_NG, client->peerid, 0, -1, 1752 NULL, 0); 1753 } 1754 ipcp_dae_reset_request(assign); 1755 out: 1756 if (radres != NULL) 1757 radius_delete_packet(radres); 1758 } 1759 1760 void 1761 ipcp_dae_reset_request(struct assigned_ipv4 *assign) 1762 { 1763 struct radiusctl_client *client, *clientt; 1764 const struct timeval zero = { 0, 0 }; 1765 1766 if (assign->dae != NULL) { 1767 if (assign->dae_reqpkt != NULL) 1768 TAILQ_REMOVE(&assign->dae->reqs, assign, dae_next); 1769 if (assign->dae_ntry > 0) { 1770 assign->dae->ninflight--; 1771 if (!evtimer_pending(&assign->dae->ev_reqs, NULL)) 1772 evtimer_add(&assign->dae->ev_reqs, &zero); 1773 } 1774 } 1775 if (assign->dae_reqpkt != NULL) 1776 radius_delete_packet(assign->dae_reqpkt); 1777 assign->dae_reqpkt = NULL; 1778 if (evtimer_pending(&assign->dae_evtimer, NULL)) 1779 evtimer_del(&assign->dae_evtimer); 1780 TAILQ_FOREACH_SAFE(client, &assign->dae_clients, entry, clientt) { 1781 TAILQ_REMOVE(&assign->dae_clients, client, entry); 1782 free(client); 1783 } 1784 assign->dae_ntry = 0; 1785 } 1786 1787 void 1788 ipcp_dae_send_pending_requests(int fd, short ev, void *ctx) 1789 { 1790 struct module_ipcp_dae *dae = ctx; 1791 struct module_ipcp *self = dae->ipcp; 1792 struct assigned_ipv4 *assign, *assignt; 1793 1794 ipcp_update_time(self); 1795 1796 TAILQ_FOREACH_SAFE(assign, &dae->reqs, dae_next, assignt) { 1797 if (dae->ninflight >= RADIUSD_IPCP_DAE_MAX_INFLIGHT) 1798 break; 1799 if (assign->dae_ntry == 0) /* pending */ 1800 ipcp_dae_send_disconnect_request(assign); 1801 } 1802 } 1803 1804 /*********************************************************************** 1805 * Miscellaneous functions 1806 ***********************************************************************/ 1807 struct ipcp_address * 1808 parse_address_range(const char *range) 1809 { 1810 char *buf, *sep; 1811 int masklen; 1812 uint32_t mask; 1813 struct in_addr start, end; 1814 struct ipcp_address *ret; 1815 const char *errstr; 1816 1817 buf = strdup(range); 1818 if (buf == NULL) 1819 goto error; 1820 if ((sep = strchr(buf, '-')) != NULL) { 1821 *sep = '\0'; 1822 if (inet_pton(AF_INET, buf, &start) != 1) 1823 goto error; 1824 else if (inet_pton(AF_INET, ++sep, &end) != 1) 1825 goto error; 1826 start.s_addr = ntohl(start.s_addr); 1827 end.s_addr = ntohl(end.s_addr); 1828 if (end.s_addr < start.s_addr) 1829 goto error; 1830 } else { 1831 if ((sep = strchr(buf, '/')) != NULL) { 1832 *sep = '\0'; 1833 if (inet_pton(AF_INET, buf, &start) != 1) 1834 goto error; 1835 masklen = strtonum(++sep, 0, 32, &errstr); 1836 if (errstr != NULL) 1837 goto error; 1838 } else { 1839 if (inet_pton(AF_INET, buf, &start) != 1) 1840 goto error; 1841 masklen = 32; 1842 } 1843 mask = 0xFFFFFFFFUL; 1844 if (masklen < 32) 1845 mask <<= (32 - masklen); 1846 start.s_addr = ntohl(start.s_addr) & mask; 1847 if (masklen == 32) 1848 end = start; 1849 else if (masklen == 31) 1850 end.s_addr = start.s_addr + 1; 1851 else { 1852 end.s_addr = start.s_addr + (1 << (32 - masklen)) - 2; 1853 start.s_addr = start.s_addr + 1; 1854 } 1855 } 1856 free(buf); 1857 if ((ret = calloc(1, sizeof(struct ipcp_address))) == NULL) 1858 return (NULL); 1859 ret->start = start; 1860 ret->end = end; 1861 ret->naddrs = end.s_addr - start.s_addr + 1; 1862 return (ret); 1863 error: 1864 free(buf); 1865 return (NULL); 1866 } 1867 1868 const char * 1869 radius_tunnel_type_string(unsigned val, const char *label) 1870 { 1871 unsigned int i; 1872 struct { 1873 const unsigned constval; 1874 const char *label; 1875 } tunnel_types[] = { 1876 { RADIUS_TUNNEL_TYPE_PPTP, "PPTP" }, 1877 { RADIUS_TUNNEL_TYPE_L2F, "L2F" }, 1878 { RADIUS_TUNNEL_TYPE_L2TP, "L2TP" }, 1879 { RADIUS_TUNNEL_TYPE_ATMP, "ATMP" }, 1880 { RADIUS_TUNNEL_TYPE_VTP, "VTP" }, 1881 { RADIUS_TUNNEL_TYPE_AH, "AH" }, 1882 { RADIUS_TUNNEL_TYPE_IP, "IP" }, 1883 { RADIUS_TUNNEL_TYPE_MOBILE, "MIN-IP-IP" }, 1884 { RADIUS_TUNNEL_TYPE_ESP, "ESP" }, 1885 { RADIUS_TUNNEL_TYPE_GRE, "GRE" }, 1886 { RADIUS_TUNNEL_TYPE_VDS, "DVS" }, 1887 /* [MS-RNAS] 3.3.5.1.9 Tunnel-Type */ 1888 { RADIUS_VENDOR_MICROSOFT << 8 | 1, 1889 "SSTP" } 1890 }; 1891 1892 if (label != NULL) { /* for conversion to the const value */ 1893 for (i = 0; i < nitems(tunnel_types); i++) { 1894 if (strcmp(tunnel_types[i].label, label) == 0) 1895 return (tunnel_types[i].label); 1896 } 1897 } 1898 1899 for (i = 0; i < nitems(tunnel_types); i++) { 1900 if (tunnel_types[i].constval == val) 1901 return (tunnel_types[i].label); 1902 } 1903 1904 return (NULL); 1905 } 1906 1907 const char * 1908 radius_terminate_cause_string(unsigned val) 1909 { 1910 unsigned int i; 1911 struct { 1912 const unsigned constval; 1913 const char *label; 1914 } terminate_causes[] = { 1915 { RADIUS_TERMNATE_CAUSE_USER_REQUEST, "User Request" }, 1916 { RADIUS_TERMNATE_CAUSE_LOST_CARRIER, "Lost Carrier" }, 1917 { RADIUS_TERMNATE_CAUSE_LOST_SERVICE, "Lost Service" }, 1918 { RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT, "Idle Timeout" }, 1919 { RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT, "Session Timeout" }, 1920 { RADIUS_TERMNATE_CAUSE_ADMIN_RESET, "Admin Reset" }, 1921 { RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT, "Admin Reboot" }, 1922 { RADIUS_TERMNATE_CAUSE_PORT_ERROR, "Port Error" }, 1923 { RADIUS_TERMNATE_CAUSE_NAS_ERROR, "NAS Error" }, 1924 { RADIUS_TERMNATE_CAUSE_NAS_RESET, "NAS Request" }, 1925 { RADIUS_TERMNATE_CAUSE_NAS_REBOOT, "NAS Reboot" }, 1926 { RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED, "Port Unneeded" }, 1927 { RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED, "Port Preempted" }, 1928 { RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED, "Port Suspended" }, 1929 { RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL, "Service Unavailable" }, 1930 { RADIUS_TERMNATE_CAUSE_CALLBACK, "Callback" }, 1931 { RADIUS_TERMNATE_CAUSE_USER_ERROR, "User Error" }, 1932 { RADIUS_TERMNATE_CAUSE_HOST_REQUEST, "Host Request" }, 1933 }; 1934 1935 for (i = 0; i < nitems(terminate_causes); i++) { 1936 if (terminate_causes[i].constval == val) 1937 return (terminate_causes[i].label); 1938 } 1939 1940 return (NULL); 1941 } 1942 1943 const char * 1944 radius_error_cause_string(unsigned val) 1945 { 1946 unsigned int i; 1947 struct { 1948 const unsigned constval; 1949 const char *label; 1950 } error_causes[] = { 1951 { RADIUS_ERROR_CAUSE_RESIDUAL_SESSION_REMOVED, 1952 "Residual Session Context Removed" }, 1953 { RADIUS_ERROR_CAUSE_INVALID_EAP_PACKET, 1954 "Invalid EAP Packet (Ignored)" }, 1955 { RADIUS_ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE, 1956 "Unsupported Attribute" }, 1957 { RADIUS_ERROR_CAUSE_MISSING_ATTRIBUTE, 1958 "Missing Attribute" }, 1959 { RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH, 1960 "NAS Identification Mismatch" }, 1961 { RADIUS_ERROR_CAUSE_INVALID_REQUEST, 1962 "Invalid Request" }, 1963 { RADIUS_ERROR_CAUSE_UNSUPPORTED_SERVICE, 1964 "Unsupported Service" }, 1965 { RADIUS_ERROR_CAUSE_UNSUPPORTED_EXTENSION, 1966 "Unsupported Extension" }, 1967 { RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE, 1968 "Invalid Attribute Value" }, 1969 { RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED, 1970 "Administratively Prohibited" }, 1971 { RADIUS_ERROR_CAUSE_REQUEST_NOT_ROUTABLE, 1972 "Request Not Routable (Proxy)" }, 1973 { RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND, 1974 "Session Context Not Found" }, 1975 { RADIUS_ERROR_CAUSE_SESSION_NOT_REMOVABLE, 1976 "Session Context Not Removable" }, 1977 { RADIUS_ERROR_CAUSE_OTHER_PROXY_PROCESSING_ERROR, 1978 "Other Proxy Processing Error" }, 1979 { RADIUS_ERROR_CAUSE_RESOURCES_UNAVAILABLE, 1980 "Resources Unavailable" }, 1981 { RADIUS_ERROR_CAUSE_REQUEST_INITIATED, 1982 "equest Initiated" }, 1983 { RADIUS_ERROR_CAUSE_MULTI_SELECTION_UNSUPPORTED, 1984 "Multiple Session Selection Unsupported" } 1985 }; 1986 1987 for (i = 0; i < nitems(error_causes); i++) { 1988 if (error_causes[i].constval == val) 1989 return (error_causes[i].label); 1990 } 1991 1992 return (NULL); 1993 } 1994 1995 int 1996 parse_addr(const char *str0, int af, struct sockaddr *sa, socklen_t salen) 1997 { 1998 int error; 1999 char *str, *end, *colon, *colon0, *addr = NULL, *port = NULL; 2000 char *sb, *sb0; 2001 struct addrinfo hints, *ai; 2002 2003 if ((str = strdup(str0)) == NULL) 2004 return (-1); 2005 if (*str == '[' && (end = strchr(str + 1, ']')) != NULL) { 2006 addr = str + 1; 2007 *end = '\0'; 2008 if (*(end + 1) == ':') 2009 port = end + 2; 2010 else if (*(end + 1) == '[' && (sb = strrchr(end + 2, ']')) 2011 != NULL) { 2012 port = end + 2; 2013 *sb = '\0'; 2014 } 2015 } else if ((sb0 = strchr(str, '[')) != NULL && 2016 (sb = strrchr(sb0 + 1, ']')) != NULL && sb0 < sb) { 2017 addr = str; 2018 *sb0 = '\0'; 2019 port = sb0 + 1; 2020 *sb = '\0'; 2021 } else if ((colon0 = strchr(str, ':')) != NULL && 2022 (colon = strrchr(str, ':')) != NULL && colon0 == colon) { 2023 /* has one : */ 2024 addr = str; 2025 *colon = '\0'; 2026 port = colon + 1; 2027 } else { 2028 addr = str; 2029 port = NULL; 2030 } 2031 2032 memset(&hints, 0, sizeof(hints)); 2033 hints.ai_family = af; 2034 hints.ai_socktype = SOCK_DGRAM; 2035 hints.ai_flags = AI_NUMERICHOST; 2036 if (port != NULL) 2037 hints.ai_flags |= AI_NUMERICSERV; 2038 if ((error = getaddrinfo(addr, port, &hints, &ai)) != 0) { 2039 free(str); 2040 return (-1); 2041 } 2042 free(str); 2043 if (salen < ai->ai_addrlen) { 2044 freeaddrinfo(ai); 2045 return (-1); 2046 } 2047 memcpy(sa, ai->ai_addr, ai->ai_addrlen); 2048 freeaddrinfo(ai); 2049 2050 return (0); 2051 } 2052 2053 const char * 2054 print_addr(struct sockaddr *sa, char *buf, size_t bufsiz) 2055 { 2056 int noport, ret; 2057 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 2058 2059 if (ntohs(((struct sockaddr_in *)sa)->sin_port) == 0) { 2060 noport = 1; 2061 ret = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 2062 NI_NUMERICHOST); 2063 } else { 2064 noport = 0; 2065 ret = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf, 2066 sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); 2067 } 2068 if (ret != 0) 2069 return ""; 2070 if (noport) 2071 strlcpy(buf, hbuf, bufsiz); 2072 else if (sa->sa_family == AF_INET6) 2073 snprintf(buf, bufsiz, "[%s]:%s", hbuf, sbuf); 2074 else 2075 snprintf(buf, bufsiz, "%s:%s", hbuf, sbuf); 2076 2077 return (buf); 2078 } 2079