radius.c revision 1.3
1/* $OpenBSD: radius.c,v 1.3 2024/07/13 12:22:46 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 <arpa/inet.h> 24#include <netinet/ip_ipsp.h> 25 26#include <endian.h> 27#include <event.h> 28#include <errno.h> 29#include <imsg.h> 30#include <limits.h> 31#include <netinet/in.h> 32#include <radius.h> 33#include <stdint.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <strings.h> 38#include <time.h> 39 40#include "iked.h" 41#include "eap.h" 42#include "ikev2.h" 43#include "types.h" 44 45void iked_radius_request_send(struct iked *, void *); 46void iked_radius_fill_attributes(struct iked_sa *, RADIUS_PACKET *); 47void iked_radius_config(struct iked_radserver_req *, const RADIUS_PACKET *, 48 int, uint32_t, uint8_t); 49void iked_radius_acct_request(struct iked *, struct iked_sa *, uint8_t); 50 51const struct iked_radcfgmap radius_cfgmaps[] = { 52 { IKEV2_CFG_INTERNAL_IP4_ADDRESS, 0, RADIUS_TYPE_FRAMED_IP_ADDRESS }, 53 { IKEV2_CFG_INTERNAL_IP4_NETMASK, 0, RADIUS_TYPE_FRAMED_IP_NETMASK }, 54 { IKEV2_CFG_INTERNAL_IP4_DNS, RADIUS_VENDOR_MICROSOFT, 55 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER }, 56 { IKEV2_CFG_INTERNAL_IP4_DNS, RADIUS_VENDOR_MICROSOFT, 57 RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER }, 58 { IKEV2_CFG_INTERNAL_IP4_NBNS, RADIUS_VENDOR_MICROSOFT, 59 RADIUS_VTYPE_MS_PRIMARY_NBNS_SERVER }, 60 { IKEV2_CFG_INTERNAL_IP4_NBNS, RADIUS_VENDOR_MICROSOFT, 61 RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER }, 62 { 0 } 63}; 64 65int 66iked_radius_request(struct iked *env, struct iked_sa *sa, 67 struct iked_message *msg) 68{ 69 struct eap_message *eap; 70 RADIUS_PACKET *pkt; 71 size_t len; 72 73 eap = ibuf_data(msg->msg_eapmsg); 74 len = betoh16(eap->eap_length); 75 if (eap->eap_code != EAP_CODE_RESPONSE) { 76 log_debug("%s: eap_code is not response %u", __func__, 77 (unsigned)eap->eap_code); 78 return -1; 79 } 80 81 if (eap->eap_type == EAP_TYPE_IDENTITY) { 82 if ((sa->sa_radreq = calloc(1, 83 sizeof(struct iked_radserver_req))) == NULL) { 84 log_debug( 85 "%s: calloc failed for iked_radserver_req: %s", 86 __func__, strerror(errno)); 87 return (-1); 88 } 89 timer_set(env, &sa->sa_radreq->rr_timer, 90 iked_radius_request_send, sa->sa_radreq); 91 sa->sa_radreq->rr_user = strdup(msg->msg_eap.eam_identity); 92 } 93 94 if ((pkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST)) 95 == NULL) { 96 log_debug("%s: radius_new_request_packet failed %s", __func__, 97 strerror(errno)); 98 return -1; 99 } 100 101 radius_put_string_attr(pkt, RADIUS_TYPE_USER_NAME, 102 sa->sa_radreq->rr_user); 103 if (sa->sa_radreq->rr_state != NULL) 104 radius_put_raw_attr(pkt, RADIUS_TYPE_STATE, 105 ibuf_data(sa->sa_radreq->rr_state), 106 ibuf_size(sa->sa_radreq->rr_state)); 107 108 if (radius_put_raw_attr_cat(pkt, RADIUS_TYPE_EAP_MESSAGE, 109 (uint8_t *)eap, len) == -1) { 110 log_debug("%s: radius_put_raw_attr_cat failed %s", __func__, 111 strerror(errno)); 112 return -1; 113 } 114 115 iked_radius_fill_attributes(sa, pkt); 116 117 /* save the request, it'll be needed for message authentication */ 118 if (sa->sa_radreq->rr_reqpkt != NULL) 119 radius_delete_packet(sa->sa_radreq->rr_reqpkt); 120 sa->sa_radreq->rr_reqpkt = pkt; 121 sa->sa_radreq->rr_sa = sa; 122 sa->sa_radreq->rr_ntry = 0; 123 124 iked_radius_request_send(env, sa->sa_radreq); 125 126 return 0; 127} 128 129void 130iked_radius_request_free(struct iked *env, struct iked_radserver_req *req) 131{ 132 if (req == NULL) 133 return; 134 timer_del(env, &req->rr_timer); 135 free(req->rr_user); 136 ibuf_free(req->rr_state); 137 if (req->rr_reqpkt) 138 radius_delete_packet(req->rr_reqpkt); 139 if (req->rr_sa) 140 req->rr_sa->sa_radreq = NULL; 141 if (req->rr_server) 142 TAILQ_REMOVE(&req->rr_server->rs_reqs, req, rr_entry); 143 free(req); 144} 145 146void 147iked_radius_on_event(int fd, short ev, void *ctx) 148{ 149 struct iked *env; 150 struct iked_radserver *server = ctx; 151 struct iked_radserver_req *req; 152 const struct iked_radcfgmap *cfgmap; 153 RADIUS_PACKET *pkt; 154 int i, resid; 155 struct ibuf *e; 156 const void *attrval; 157 size_t attrlen; 158 uint8_t code; 159 char username[256]; 160 u_char eapmsk[128]; 161 /* RFC 3748 defines the MSK minimum size is 64 bytes */ 162 size_t eapmsksiz = sizeof(eapmsk); 163 164 env = server->rs_env; 165 pkt = radius_recv(server->rs_sock, 0); 166 if (pkt == NULL) { 167 log_info("%s: receiving a RADIUS message failed: %s", __func__, 168 strerror(errno)); 169 return; 170 } 171 resid = radius_get_id(pkt); 172 173 TAILQ_FOREACH(req, &server->rs_reqs, rr_entry) { 174 if (req->rr_reqid == resid) 175 break; 176 } 177 if (req == NULL) { 178 log_debug("%s: received an unknown RADIUS message: id=%u", 179 __func__, (unsigned)resid); 180 return; 181 } 182 183 radius_set_request_packet(pkt, req->rr_reqpkt); 184 if (radius_check_response_authenticator(pkt, server->rs_secret) != 0) { 185 log_info("%s: received an invalid RADIUS message: bad " 186 "response authenticator", __func__); 187 return; 188 } 189 if (req->rr_accounting) { 190 /* accounting */ 191 code = radius_get_code(pkt); 192 switch (code) { 193 case RADIUS_CODE_ACCOUNTING_RESPONSE: /* Expected */ 194 break; 195 default: 196 log_info("%s: received an invalid RADIUS message: " 197 "code %u", __func__, (unsigned)code); 198 } 199 timer_del(env, &req->rr_timer); 200 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 201 req->rr_server = NULL; 202 free(req); 203 return; 204 } 205 206 /* authentication */ 207 if (radius_check_message_authenticator(pkt, server->rs_secret) != 0) { 208 log_info("%s: received an invalid RADIUS message: bad " 209 "message authenticator", __func__); 210 return; 211 } 212 213 timer_del(env, &req->rr_timer); 214 req->rr_ntry = 0; 215 216 if (req->rr_sa == NULL) 217 goto fail; 218 219 code = radius_get_code(pkt); 220 switch (code) { 221 case RADIUS_CODE_ACCESS_CHALLENGE: 222 if (radius_get_raw_attr_ptr(pkt, RADIUS_TYPE_STATE, &attrval, 223 &attrlen) != 0) { 224 log_info("%s: received an invalid RADIUS message: no " 225 "state attribute", __func__); 226 goto fail; 227 } 228 if ((req->rr_state != NULL && 229 ibuf_set(req->rr_state, 0, attrval, attrlen) != 0) || 230 (req->rr_state = ibuf_new(attrval, attrlen)) == NULL) { 231 log_info("%s: ibuf_new() failed: %s", __func__, 232 strerror(errno)); 233 goto fail; 234 } 235 break; 236 case RADIUS_CODE_ACCESS_ACCEPT: 237 log_info("%s: received Access-Accept for %s", 238 SPI_SA(req->rr_sa, __func__), req->rr_user); 239 /* Try to retrieve the EAP MSK from the RADIUS response */ 240 if (radius_get_eap_msk(pkt, eapmsk, &eapmsksiz, 241 server->rs_secret) == 0) { 242 ibuf_free(req->rr_sa->sa_eapmsk); 243 if ((req->rr_sa->sa_eapmsk = ibuf_new(eapmsk, 244 eapmsksiz)) == NULL) { 245 log_info("%s: ibuf_new() failed: %s", __func__, 246 strerror(errno)); 247 goto fail; 248 } 249 } else 250 log_debug("Could not retrieve the EAP MSK from the " 251 "RADIUS message"); 252 253 free(req->rr_sa->sa_eapid); 254 /* The EAP identity might be protected (RFC 3748 7.3) */ 255 if (radius_get_string_attr(pkt, RADIUS_TYPE_USER_NAME, 256 username, sizeof(username)) == 0 && 257 strcmp(username, req->rr_user) != 0) { 258 /* 259 * The Access-Accept might have a User-Name. It 260 * should be used for Accouting (RFC 2865 5.1). 261 */ 262 free(req->rr_user); 263 req->rr_sa->sa_eapid = strdup(username); 264 } else 265 req->rr_sa->sa_eapid = req->rr_user; 266 req->rr_user = NULL; 267 268 sa_state(env, req->rr_sa, IKEV2_STATE_AUTH_SUCCESS); 269 270 /* Map RADIUS attributes to cp */ 271 if (TAILQ_EMPTY(&env->sc_radcfgmaps)) { 272 for (i = 0; radius_cfgmaps[i].cfg_type != 0; i++) { 273 cfgmap = &radius_cfgmaps[i]; 274 iked_radius_config(req, pkt, cfgmap->cfg_type, 275 cfgmap->vendor_id, cfgmap->attr_type); 276 } 277 } else { 278 TAILQ_FOREACH(cfgmap, &env->sc_radcfgmaps, entry) 279 iked_radius_config(req, pkt, cfgmap->cfg_type, 280 cfgmap->vendor_id, cfgmap->attr_type); 281 } 282 283 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 284 req->rr_server = NULL; 285 break; 286 case RADIUS_CODE_ACCESS_REJECT: 287 log_info("%s: received Access-Reject for %s", 288 SPI_SA(req->rr_sa, __func__), req->rr_user); 289 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 290 req->rr_server = NULL; 291 break; 292 default: 293 log_debug("%s: received an invalid RADIUS message: code %u", 294 __func__, (unsigned)code); 295 break; 296 } 297 298 /* get the length first */ 299 if (radius_get_raw_attr_cat(pkt, RADIUS_TYPE_EAP_MESSAGE, NULL, 300 &attrlen) != 0) { 301 log_info("%s: failed to retrieve the EAP message", __func__); 302 goto fail; 303 } 304 /* allocate a buffer */ 305 if ((e = ibuf_new(NULL, attrlen)) == NULL) { 306 log_info("%s: ibuf_new() failed: %s", __func__, 307 strerror(errno)); 308 goto fail; 309 } 310 /* copy the message to the buffer */ 311 if (radius_get_raw_attr_cat(pkt, RADIUS_TYPE_EAP_MESSAGE, 312 ibuf_data(e), &attrlen) != 0) { 313 ibuf_free(e); 314 log_info("%s: failed to retrieve the EAP message", __func__); 315 goto fail; 316 } 317 ikev2_send_ike_e(env, req->rr_sa, e, IKEV2_PAYLOAD_EAP, 318 IKEV2_EXCHANGE_IKE_AUTH, 1); 319 return; 320 fail: 321 if (req->rr_server != NULL) 322 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 323 req->rr_server = NULL; 324 if (req->rr_sa != NULL) { 325 ikev2_ike_sa_setreason(req->rr_sa, "RADIUS request failed"); 326 sa_free(env, req->rr_sa); 327 } 328} 329 330void 331iked_radius_request_send(struct iked *env, void *ctx) 332{ 333 struct iked_radserver_req *req = ctx, *req0; 334 struct iked_radserver *server = req->rr_server; 335 const int timeouts[] = { 2, 4, 8 }; 336 uint8_t seq; 337 int i, max_tries, max_failovers; 338 struct sockaddr_storage ss; 339 socklen_t sslen; 340 struct iked_radservers *radservers; 341 struct timespec now; 342 343 if (!req->rr_accounting) { 344 max_tries = env->sc_radauth.max_tries; 345 max_failovers = env->sc_radauth.max_failovers; 346 radservers = &env->sc_radauthservers; 347 } else { 348 max_tries = env->sc_radacct.max_tries; 349 max_failovers = env->sc_radacct.max_failovers; 350 radservers = &env->sc_radacctservers; 351 } 352 353 if (req->rr_ntry > max_tries) { 354 req->rr_ntry = 0; 355 log_info("%s: RADIUS server %s failed", __func__, 356 print_addr(&server->rs_sockaddr)); 357 next_server: 358 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 359 req->rr_server = NULL; 360 if (req->rr_nfailover >= max_failovers || 361 TAILQ_NEXT(server, rs_entry) == NULL) { 362 log_info("%s: No more RADIUS server", __func__); 363 goto fail; 364 } else if (req->rr_state != NULL) { 365 log_info("%s: Can't change RADIUS server: " 366 "client has a state already", __func__); 367 goto fail; 368 } else { 369 TAILQ_REMOVE(radservers, server, rs_entry); 370 TAILQ_INSERT_TAIL(radservers, server, rs_entry); 371 server = TAILQ_FIRST(radservers); 372 log_info("%s: RADIUS server %s is active", 373 __func__, print_addr(&server->rs_sockaddr)); 374 } 375 req->rr_nfailover++; 376 } 377 378 if (req->rr_server != NULL && 379 req->rr_server != TAILQ_FIRST(radservers)) { 380 /* Current server is marked fail */ 381 if (req->rr_state != NULL || req->rr_nfailover >= max_failovers) 382 goto fail; /* can't fail over */ 383 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 384 req->rr_server = NULL; 385 req->rr_nfailover++; 386 } 387 388 if (req->rr_server == NULL) { 389 /* Select a new server */ 390 server = TAILQ_FIRST(radservers); 391 if (server == NULL) { 392 log_info("%s: No RADIUS server is configured", 393 __func__); 394 goto fail; 395 } 396 TAILQ_INSERT_TAIL(&server->rs_reqs, req, rr_entry); 397 req->rr_server = server; 398 399 /* Prepare NAS-IP-Address */ 400 if (server->rs_nas_ipv4.s_addr == INADDR_ANY && 401 IN6_IS_ADDR_UNSPECIFIED(&server->rs_nas_ipv6)) { 402 sslen = sizeof(ss); 403 if (getsockname(server->rs_sock, (struct sockaddr *)&ss, 404 &sslen) == 0) { 405 if (ss.ss_family == AF_INET) 406 server->rs_nas_ipv4 = 407 ((struct sockaddr_in *)&ss) 408 ->sin_addr; 409 else 410 server->rs_nas_ipv6 = 411 ((struct sockaddr_in6 *)&ss) 412 ->sin6_addr; 413 } 414 } 415 } 416 if (req->rr_ntry == 0) { 417 /* decide the ID */ 418 seq = ++server->rs_reqseq; 419 for (i = 0; i < UCHAR_MAX; i++) { 420 TAILQ_FOREACH(req0, &server->rs_reqs, rr_entry) { 421 if (req0->rr_reqid == seq) 422 break; 423 } 424 if (req0 == NULL) 425 break; 426 seq++; 427 } 428 if (i >= UCHAR_MAX) { 429 log_info("%s: RADIUS server %s failed. Too many " 430 "pending requests", __func__, 431 print_addr(&server->rs_sockaddr)); 432 if (TAILQ_NEXT(server, rs_entry) != NULL) 433 goto next_server; 434 goto fail; 435 } 436 req->rr_reqid = seq; 437 radius_set_id(req->rr_reqpkt, req->rr_reqid); 438 } 439 440 if (server->rs_nas_ipv4.s_addr != INADDR_ANY) 441 radius_put_ipv4_attr(req->rr_reqpkt, RADIUS_TYPE_NAS_IP_ADDRESS, 442 server->rs_nas_ipv4); 443 else if (!IN6_IS_ADDR_UNSPECIFIED(&server->rs_nas_ipv6)) 444 radius_put_ipv6_attr(req->rr_reqpkt, 445 RADIUS_TYPE_NAS_IPV6_ADDRESS, &server->rs_nas_ipv6); 446 /* Identifier */ 447 radius_put_string_attr(req->rr_reqpkt, RADIUS_TYPE_NAS_IDENTIFIER, 448 IKED_NAS_ID); 449 450 if (req->rr_accounting) { 451 if (req->rr_ntry == 0 && req->rr_nfailover == 0) 452 radius_put_uint32_attr(req->rr_reqpkt, 453 RADIUS_TYPE_ACCT_DELAY_TIME, 0); 454 else { 455 clock_gettime(CLOCK_MONOTONIC, &now); 456 timespecsub(&now, &req->rr_accttime, &now); 457 radius_put_uint32_attr(req->rr_reqpkt, 458 RADIUS_TYPE_ACCT_DELAY_TIME, now.tv_sec); 459 } 460 radius_set_accounting_request_authenticator(req->rr_reqpkt, 461 server->rs_secret); 462 } else { 463 radius_put_message_authenticator(req->rr_reqpkt, 464 server->rs_secret); 465 } 466 467 if (radius_send(server->rs_sock, req->rr_reqpkt, 0) < 0) 468 log_info("%s: sending a RADIUS message failed: %s", __func__, 469 strerror(errno)); 470 471 if (req->rr_ntry >= (int)nitems(timeouts)) 472 timer_add(env, &req->rr_timer, timeouts[nitems(timeouts) - 1]); 473 else 474 timer_add(env, &req->rr_timer, timeouts[req->rr_ntry]); 475 req->rr_ntry++; 476 return; 477 fail: 478 if (req->rr_server != NULL) 479 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 480 req->rr_server = NULL; 481 if (req->rr_sa != NULL) { 482 ikev2_ike_sa_setreason(req->rr_sa, "RADIUS request failed"); 483 sa_free(env, req->rr_sa); 484 } 485} 486 487void 488iked_radius_fill_attributes(struct iked_sa *sa, RADIUS_PACKET *pkt) 489{ 490 /* NAS Port Type = Virtual */ 491 radius_put_uint32_attr(pkt, 492 RADIUS_TYPE_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_VIRTUAL); 493 /* Service Type = Framed */ 494 radius_put_uint32_attr(pkt, RADIUS_TYPE_SERVICE_TYPE, 495 RADIUS_SERVICE_TYPE_FRAMED); 496 /* Tunnel Type = EAP */ 497 radius_put_uint32_attr(pkt, RADIUS_TYPE_TUNNEL_TYPE, 498 RADIUS_TUNNEL_TYPE_ESP); 499 500 radius_put_string_attr(pkt, RADIUS_TYPE_CALLED_STATION_ID, 501 print_addr(&sa->sa_local.addr)); 502 radius_put_string_attr(pkt, RADIUS_TYPE_CALLING_STATION_ID, 503 print_addr(&sa->sa_peer.addr)); 504} 505 506void 507iked_radius_config(struct iked_radserver_req *req, const RADIUS_PACKET *pkt, 508 int cfg_type, uint32_t vendor_id, uint8_t attr_type) 509{ 510 unsigned int i; 511 struct iked_sa *sa = req->rr_sa; 512 struct in_addr ia4; 513 struct in6_addr ia6; 514 struct sockaddr_in *sin4; 515 struct sockaddr_in6 *sin6; 516 struct iked_addr *addr; 517 struct iked_cfg *ikecfg; 518 519 for (i = 0; i < sa->sa_policy->pol_ncfg; i++) { 520 ikecfg = &sa->sa_policy->pol_cfg[i]; 521 if (ikecfg->cfg_type == cfg_type && 522 ikecfg->cfg_type != IKEV2_CFG_INTERNAL_IP4_ADDRESS) 523 return; /* use config rather than radius */ 524 } 525 switch (cfg_type) { 526 case IKEV2_CFG_INTERNAL_IP4_ADDRESS: 527 case IKEV2_CFG_INTERNAL_IP4_NETMASK: 528 case IKEV2_CFG_INTERNAL_IP4_DNS: 529 case IKEV2_CFG_INTERNAL_IP4_NBNS: 530 case IKEV2_CFG_INTERNAL_IP4_DHCP: 531 case IKEV2_CFG_INTERNAL_IP4_SERVER: 532 if (vendor_id == 0 && radius_has_attr(pkt, attr_type)) 533 radius_get_ipv4_attr(pkt, attr_type, &ia4); 534 else if (vendor_id != 0 && radius_has_vs_attr(pkt, vendor_id, 535 attr_type)) 536 radius_get_vs_ipv4_attr(pkt, vendor_id, attr_type, 537 &ia4); 538 else 539 break; /* no attribute contained */ 540 541 if (cfg_type == IKEV2_CFG_INTERNAL_IP4_NETMASK) { 542 /* 543 * This assumes IKEV2_CFG_INTERNAL_IP4_ADDRESS is 544 * called before IKEV2_CFG_INTERNAL_IP4_NETMASK 545 */ 546 if (sa->sa_rad_addr == NULL) { 547 /* 548 * RFC 7296, IKEV2_CFG_INTERNAL_IP4_NETMASK 549 * must be used with 550 * IKEV2_CFG_INTERNAL_IP4_ADDRESS 551 */ 552 break; 553 } 554 if (ia4.s_addr == 0) { 555 log_debug("%s: netmask is wrong", __func__); 556 break; 557 } 558 if (ia4.s_addr == htonl(0)) 559 sa->sa_rad_addr->addr_mask = 0; 560 else 561 sa->sa_rad_addr->addr_mask = 562 33 - ffs(ntohl(ia4.s_addr)); 563 if (sa->sa_rad_addr->addr_mask < 32) 564 sa->sa_rad_addr->addr_net = 1; 565 } 566 if (cfg_type == IKEV2_CFG_INTERNAL_IP4_ADDRESS) { 567 if ((addr = calloc(1, sizeof(*addr))) == NULL) { 568 log_warn("%s: calloc", __func__); 569 return; 570 } 571 sa->sa_rad_addr = addr; 572 } else { 573 req->rr_cfg[req->rr_ncfg].cfg_action = IKEV2_CP_REPLY; 574 req->rr_cfg[req->rr_ncfg].cfg_type = cfg_type; 575 addr = &req->rr_cfg[req->rr_ncfg].cfg.address; 576 req->rr_ncfg++; 577 } 578 addr->addr_af = AF_INET; 579 sin4 = (struct sockaddr_in *)&addr->addr; 580 sin4->sin_family = AF_INET; 581 sin4->sin_len = sizeof(struct sockaddr_in); 582 sin4->sin_addr = ia4; 583 break; 584 case IKEV2_CFG_INTERNAL_IP6_ADDRESS: 585 case IKEV2_CFG_INTERNAL_IP6_DNS: 586 case IKEV2_CFG_INTERNAL_IP6_NBNS: 587 case IKEV2_CFG_INTERNAL_IP6_DHCP: 588 case IKEV2_CFG_INTERNAL_IP6_SERVER: 589 if (vendor_id == 0 && radius_has_attr(pkt, attr_type)) 590 radius_get_ipv6_attr(pkt, attr_type, &ia6); 591 else if (vendor_id != 0 && radius_has_vs_attr(pkt, vendor_id, 592 attr_type)) 593 radius_get_vs_ipv6_attr(pkt, vendor_id, attr_type, 594 &ia6); 595 else 596 break; /* no attribute contained */ 597 598 if (cfg_type == IKEV2_CFG_INTERNAL_IP6_ADDRESS) { 599 if ((addr = calloc(1, sizeof(*addr))) == NULL) { 600 log_warn("%s: calloc", __func__); 601 return; 602 } 603 sa->sa_rad_addr = addr; 604 } else { 605 req->rr_cfg[req->rr_ncfg].cfg_action = IKEV2_CP_REPLY; 606 req->rr_cfg[req->rr_ncfg].cfg_type = cfg_type; 607 addr = &req->rr_cfg[req->rr_ncfg].cfg.address; 608 req->rr_ncfg++; 609 } 610 addr->addr_af = AF_INET; 611 sin6 = (struct sockaddr_in6 *)&addr->addr; 612 sin6->sin6_family = AF_INET6; 613 sin6->sin6_len = sizeof(struct sockaddr_in6); 614 sin6->sin6_addr = ia6; 615 break; 616 } 617 return; 618} 619 620void 621iked_radius_acct_on(struct iked *env) 622{ 623 if (TAILQ_EMPTY(&env->sc_radacctservers)) 624 return; 625 if (env->sc_radaccton == 0) { /* trigger once */ 626 iked_radius_acct_request(env, NULL, 627 RADIUS_ACCT_STATUS_TYPE_ACCT_ON); 628 env->sc_radaccton = 1; 629 } 630} 631 632void 633iked_radius_acct_off(struct iked *env) 634{ 635 iked_radius_acct_request(env, NULL, RADIUS_ACCT_STATUS_TYPE_ACCT_OFF); 636} 637 638void 639iked_radius_acct_start(struct iked *env, struct iked_sa *sa) 640{ 641 iked_radius_acct_request(env, sa, RADIUS_ACCT_STATUS_TYPE_START); 642} 643 644void 645iked_radius_acct_stop(struct iked *env, struct iked_sa *sa) 646{ 647 iked_radius_acct_request(env, sa, RADIUS_ACCT_STATUS_TYPE_STOP); 648} 649 650void 651iked_radius_acct_request(struct iked *env, struct iked_sa *sa, uint8_t stype) 652{ 653 struct iked_radserver_req *req; 654 RADIUS_PACKET *pkt; 655 struct iked_addr *addr4 = NULL; 656 struct iked_addr *addr6 = NULL; 657 struct in_addr mask4; 658 char sa_id[IKED_ID_SIZE]; 659 char sid[16 + 1]; 660 struct timespec now; 661 int cause; 662 663 if (TAILQ_EMPTY(&env->sc_radacctservers)) 664 return; 665 /* 666 * In RFC2866 5.6, "Users who are delivered service without 667 * being authenticated SHOULD NOT generate Accounting records 668 */ 669 if (sa != NULL && sa->sa_eapid == NULL) { 670 /* fallback to IKEID for accounting */ 671 if (ikev2_print_id(IKESA_DSTID(sa), sa_id, sizeof(sa_id)) != -1) 672 sa->sa_eapid = strdup(sa_id); 673 if (sa->sa_eapid == NULL) 674 return; 675 } 676 677 if ((req = calloc(1, sizeof(struct iked_radserver_req))) == NULL) { 678 log_debug("%s: calloc faile for iked_radserver_req: %s", 679 __func__, strerror(errno)); 680 return; 681 } 682 req->rr_accounting = 1; 683 clock_gettime(CLOCK_MONOTONIC, &now); 684 req->rr_accttime = now; 685 timer_set(env, &req->rr_timer, iked_radius_request_send, req); 686 687 if ((pkt = radius_new_request_packet(RADIUS_CODE_ACCOUNTING_REQUEST)) 688 == NULL) { 689 log_debug("%s: radius_new_request_packet failed %s", __func__, 690 strerror(errno)); 691 return; 692 } 693 694 /* RFC 2866 5.1. Acct-Status-Type */ 695 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_STATUS_TYPE, stype); 696 697 if (sa == NULL) { 698 /* ASSERT(stype == RADIUS_ACCT_STATUS_TYPE_ACCT_ON || 699 stype == RADIUS_ACCT_STATUS_TYPE_ACCT_OFF) */ 700 req->rr_reqpkt = pkt; 701 req->rr_ntry = 0; 702 iked_radius_request_send(env, req); 703 return; 704 } 705 706 iked_radius_fill_attributes(sa, pkt); 707 708 radius_put_string_attr(pkt, RADIUS_TYPE_USER_NAME, sa->sa_eapid); 709 710 /* RFC 2866 5.5. Acct-Session-Id */ 711 snprintf(sid, sizeof(sid), "%016llx", 712 (unsigned long long)sa->sa_hdr.sh_ispi); 713 radius_put_string_attr(pkt, RADIUS_TYPE_ACCT_SESSION_ID, sid); 714 715 /* Accounting Request must have Framed-IP-Address */ 716 addr4 = sa->sa_addrpool; 717 if (addr4 != NULL) { 718 radius_put_ipv4_attr(pkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, 719 ((struct sockaddr_in *)&addr4->addr)->sin_addr); 720 if (addr4->addr_mask != 0) { 721 mask4.s_addr = htonl( 722 0xFFFFFFFFUL << (32 - addr4->addr_mask)); 723 radius_put_ipv4_attr(pkt, 724 RADIUS_TYPE_FRAMED_IP_NETMASK, mask4); 725 } 726 } 727 addr6 = sa->sa_addrpool6; 728 if (addr6 != NULL) 729 radius_put_ipv6_attr(pkt, RADIUS_TYPE_FRAMED_IPV6_ADDRESS, 730 &((struct sockaddr_in6 *)&addr6->addr)->sin6_addr); 731 732 /* RFC2866 5.6 Acct-Authentic */ 733 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_AUTHENTIC, 734 (sa->sa_radreq != NULL)? RADIUS_ACCT_AUTHENTIC_RADIUS : 735 RADIUS_ACCT_AUTHENTIC_LOCAL); 736 737 switch (stype) { 738 case RADIUS_ACCT_STATUS_TYPE_START: 739 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_STATUS_TYPE, 740 RADIUS_ACCT_STATUS_TYPE_START); 741 break; 742 case RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE: 743 case RADIUS_ACCT_STATUS_TYPE_STOP: 744 /* RFC 2866 5.7. Acct-Session-Time */ 745 timespecsub(&now, &sa->sa_starttime, &now); 746 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_SESSION_TIME, 747 now.tv_sec); 748 /* RFC 2866 5.10 Acct-Terminate-Cause */ 749 cause = RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL; 750 if (sa->sa_reason) { 751 if (strcmp(sa->sa_reason, "received delete") == 0) { 752 cause = RADIUS_TERMNATE_CAUSE_USER_REQUEST; 753 } else if (strcmp(sa->sa_reason, "SA rekeyed") == 0) { 754 cause = RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT; 755 } else if (strncmp(sa->sa_reason, "retransmit", 756 strlen("retransmit")) == 0) { 757 cause = RADIUS_TERMNATE_CAUSE_LOST_SERVICE; 758 } else if (strcmp(sa->sa_reason, 759 "disconnect requested") == 0) { 760 cause = RADIUS_TERMNATE_CAUSE_ADMIN_RESET; 761 } 762 } 763 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_TERMINATE_CAUSE, 764 cause); 765 /* I/O statistics {Input,Output}-{Packets,Octets,Gigawords} */ 766 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_INPUT_PACKETS, 767 sa->sa_stats.sas_ipackets); 768 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS, 769 sa->sa_stats.sas_opackets); 770 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_INPUT_OCTETS, 771 sa->sa_stats.sas_ibytes & 0xffffffffUL); 772 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_OUTPUT_OCTETS, 773 sa->sa_stats.sas_obytes & 0xffffffffUL); 774 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, 775 sa->sa_stats.sas_ibytes >> 32); 776 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS, 777 sa->sa_stats.sas_obytes >> 32); 778 break; 779 } 780 req->rr_reqpkt = pkt; 781 req->rr_ntry = 0; 782 iked_radius_request_send(env, req); 783} 784 785void 786iked_radius_dae_on_event(int fd, short ev, void *ctx) 787{ 788 struct iked_raddae *dae = ctx; 789 struct iked *env = dae->rd_env; 790 RADIUS_PACKET *req = NULL, *res = NULL; 791 struct sockaddr_storage ss; 792 socklen_t sslen; 793 struct iked_radclient *client; 794 struct iked_sa *sa = NULL; 795 char attr[256], username[256]; 796 char *endp, *reason, *nakcause = NULL; 797 int code, n = 0; 798 uint64_t ispi = 0; 799 uint32_t u32, cause = 0; 800 struct iked_addr *addr4 = NULL; 801 802 reason = "disconnect requested"; 803 804 sslen = sizeof(ss); 805 req = radius_recvfrom(dae->rd_sock, 0, (struct sockaddr *)&ss, &sslen); 806 if (req == NULL) { 807 log_warn("%s: receiving a RADIUS message failed: %s", __func__, 808 strerror(errno)); 809 return; 810 } 811 TAILQ_FOREACH(client, &env->sc_raddaeclients, rc_entry) { 812 if (sockaddr_cmp((struct sockaddr *)&client->rc_sockaddr, 813 (struct sockaddr *)&ss, -1) == 0) 814 break; 815 } 816 if (client == NULL) { 817 log_warnx("%s: received RADIUS message from %s: " 818 "unknown client", __func__, print_addr(&ss)); 819 goto out; 820 } 821 822 if (radius_check_accounting_request_authenticator(req, 823 client->rc_secret) != 0) { 824 log_warnx("%s: received an invalid RADIUS message from %s: bad " 825 "response authenticator", __func__, print_addr(&ss)); 826 goto out; 827 } 828 829 if ((code = radius_get_code(req)) != RADIUS_CODE_DISCONNECT_REQUEST) { 830 /* Code other than Disconnect-Request is not supported */ 831 if (code == RADIUS_CODE_COA_REQUEST) { 832 code = RADIUS_CODE_COA_NAK; 833 cause = RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED; 834 nakcause = "Coa-Request is not supprted"; 835 goto send; 836 } 837 log_warnx("%s: received an invalid RADIUS message " 838 "from %s: unknown code %d", __func__, 839 print_addr(&ss), code); 840 goto out; 841 } 842 843 log_info("received Disconnect-Request from %s", print_addr(&ss)); 844 845 if (radius_get_string_attr(req, RADIUS_TYPE_NAS_IDENTIFIER, attr, 846 sizeof(attr)) == 0 && strcmp(attr, IKED_NAS_ID) != 0) { 847 cause = RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH; 848 nakcause = "NAS-Identifier is not matched"; 849 goto search_done; 850 } 851 852 /* prepare User-Name attribute */ 853 memset(username, 0, sizeof(username)); 854 radius_get_string_attr(req, RADIUS_TYPE_USER_NAME, username, 855 sizeof(username)); 856 857 if (radius_get_string_attr(req, RADIUS_TYPE_ACCT_SESSION_ID, attr, 858 sizeof(attr)) == 0) { 859 /* the client is to disconnect a session */ 860 ispi = strtoull(attr, &endp, 16); 861 if (attr[0] == '\0' || *endp != '\0' || errno == ERANGE || 862 ispi == ULLONG_MAX) { 863 cause = RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE; 864 nakcause = "Session-Id is wrong"; 865 goto search_done; 866 867 } 868 RB_FOREACH(sa, iked_sas, &env->sc_sas) { 869 if (sa->sa_hdr.sh_ispi == ispi) 870 break; 871 } 872 if (sa == NULL) 873 goto search_done; 874 if (username[0] != '\0' && (sa->sa_eapid == NULL || 875 strcmp(username, sa->sa_eapid) != 0)) { 876 /* specified User-Name attribute is mismatched */ 877 cause = RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE; 878 nakcause = "User-Name is not matched"; 879 goto search_done; 880 } 881 ikev2_ike_sa_setreason(sa, reason); 882 ikev2_ike_sa_delete(env, sa); 883 n++; 884 } else if (username[0] != '\0') { 885 RB_FOREACH(sa, iked_sas, &env->sc_sas) { 886 if (sa->sa_eapid != NULL && 887 strcmp(sa->sa_eapid, username) == 0) { 888 ikev2_ike_sa_setreason(sa, reason); 889 ikev2_ike_sa_delete(env, sa); 890 n++; 891 } 892 } 893 } else if (radius_get_uint32_attr(req, RADIUS_TYPE_FRAMED_IP_ADDRESS, 894 &u32) == 0) { 895 addr4 = sa->sa_addrpool; 896 if (addr4 != NULL) { 897 RB_FOREACH(sa, iked_sas, &env->sc_sas) { 898 if (u32 == ((struct sockaddr_in *)&addr4->addr) 899 ->sin_addr.s_addr) { 900 ikev2_ike_sa_setreason(sa, reason); 901 ikev2_ike_sa_delete(env, sa); 902 n++; 903 } 904 } 905 } 906 } 907 search_done: 908 if (n > 0) 909 code = RADIUS_CODE_DISCONNECT_ACK; 910 else { 911 if (nakcause == NULL) 912 nakcause = "session not found"; 913 if (cause == 0) 914 cause = RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND; 915 code = RADIUS_CODE_DISCONNECT_NAK; 916 } 917 send: 918 res = radius_new_response_packet(code, req); 919 if (res == NULL) { 920 log_warn("%s: radius_new_response_packet", __func__); 921 goto out; 922 } 923 if (cause != 0) 924 radius_put_uint32_attr(res, RADIUS_TYPE_ERROR_CAUSE, cause); 925 radius_set_response_authenticator(res, client->rc_secret); 926 if (radius_sendto(dae->rd_sock, res, 0, (struct sockaddr *)&ss, sslen) 927 == -1) 928 log_warn("%s: sendto", __func__); 929 log_info("send %s for %s%s%s", 930 (code == RADIUS_CODE_DISCONNECT_ACK)? "Disconnect-ACK" : 931 (code == RADIUS_CODE_DISCONNECT_NAK)? "Disconnect-NAK" : "CoA-NAK", 932 print_addr(&ss), (nakcause)? ": " : "", (nakcause)? nakcause : ""); 933 out: 934 radius_delete_packet(req); 935 if (res != NULL) 936 radius_delete_packet(res); 937} 938/* $OpenBSD: radius.c,v 1.3 2024/07/13 12:22:46 yasuoka Exp $ */ 939 940/* 941 * Copyright (c) 2024 Internet Initiative Japan Inc. 942 * 943 * Permission to use, copy, modify, and distribute this software for any 944 * purpose with or without fee is hereby granted, provided that the above 945 * copyright notice and this permission notice appear in all copies. 946 * 947 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 948 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 949 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 950 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 951 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 952 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 953 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 954 */ 955 956#include <sys/types.h> 957#include <sys/queue.h> 958#include <sys/socket.h> 959#include <sys/time.h> 960#include <arpa/inet.h> 961#include <netinet/ip_ipsp.h> 962 963#include <endian.h> 964#include <event.h> 965#include <errno.h> 966#include <imsg.h> 967#include <limits.h> 968#include <netinet/in.h> 969#include <radius.h> 970#include <stdint.h> 971#include <stdio.h> 972#include <stdlib.h> 973#include <string.h> 974#include <strings.h> 975#include <time.h> 976 977#include "iked.h" 978#include "eap.h" 979#include "ikev2.h" 980#include "types.h" 981 982void iked_radius_request_send(struct iked *, void *); 983void iked_radius_fill_attributes(struct iked_sa *, RADIUS_PACKET *); 984void iked_radius_config(struct iked_radserver_req *, const RADIUS_PACKET *, 985 int, uint32_t, uint8_t); 986void iked_radius_acct_request(struct iked *, struct iked_sa *, uint8_t); 987 988const struct iked_radcfgmap radius_cfgmaps[] = { 989 { IKEV2_CFG_INTERNAL_IP4_ADDRESS, 0, RADIUS_TYPE_FRAMED_IP_ADDRESS }, 990 { IKEV2_CFG_INTERNAL_IP4_NETMASK, 0, RADIUS_TYPE_FRAMED_IP_NETMASK }, 991 { IKEV2_CFG_INTERNAL_IP4_DNS, RADIUS_VENDOR_MICROSOFT, 992 RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER }, 993 { IKEV2_CFG_INTERNAL_IP4_DNS, RADIUS_VENDOR_MICROSOFT, 994 RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER }, 995 { IKEV2_CFG_INTERNAL_IP4_NBNS, RADIUS_VENDOR_MICROSOFT, 996 RADIUS_VTYPE_MS_PRIMARY_NBNS_SERVER }, 997 { IKEV2_CFG_INTERNAL_IP4_NBNS, RADIUS_VENDOR_MICROSOFT, 998 RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER }, 999 { 0 } 1000}; 1001 1002int 1003iked_radius_request(struct iked *env, struct iked_sa *sa, 1004 struct iked_message *msg) 1005{ 1006 struct eap_message *eap; 1007 RADIUS_PACKET *pkt; 1008 size_t len; 1009 1010 eap = ibuf_data(msg->msg_eapmsg); 1011 len = betoh16(eap->eap_length); 1012 if (eap->eap_code != EAP_CODE_RESPONSE) { 1013 log_debug("%s: eap_code is not response %u", __func__, 1014 (unsigned)eap->eap_code); 1015 return -1; 1016 } 1017 1018 if (eap->eap_type == EAP_TYPE_IDENTITY) { 1019 if ((sa->sa_radreq = calloc(1, 1020 sizeof(struct iked_radserver_req))) == NULL) { 1021 log_debug( 1022 "%s: calloc failed for iked_radserver_req: %s", 1023 __func__, strerror(errno)); 1024 return (-1); 1025 } 1026 timer_set(env, &sa->sa_radreq->rr_timer, 1027 iked_radius_request_send, sa->sa_radreq); 1028 sa->sa_radreq->rr_user = strdup(msg->msg_eap.eam_identity); 1029 } 1030 1031 if ((pkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST)) 1032 == NULL) { 1033 log_debug("%s: radius_new_request_packet failed %s", __func__, 1034 strerror(errno)); 1035 return -1; 1036 } 1037 1038 radius_put_string_attr(pkt, RADIUS_TYPE_USER_NAME, 1039 sa->sa_radreq->rr_user); 1040 if (sa->sa_radreq->rr_state != NULL) 1041 radius_put_raw_attr(pkt, RADIUS_TYPE_STATE, 1042 ibuf_data(sa->sa_radreq->rr_state), 1043 ibuf_size(sa->sa_radreq->rr_state)); 1044 1045 if (radius_put_raw_attr_cat(pkt, RADIUS_TYPE_EAP_MESSAGE, 1046 (uint8_t *)eap, len) == -1) { 1047 log_debug("%s: radius_put_raw_attr_cat failed %s", __func__, 1048 strerror(errno)); 1049 return -1; 1050 } 1051 1052 iked_radius_fill_attributes(sa, pkt); 1053 1054 /* save the request, it'll be needed for message authentication */ 1055 if (sa->sa_radreq->rr_reqpkt != NULL) 1056 radius_delete_packet(sa->sa_radreq->rr_reqpkt); 1057 sa->sa_radreq->rr_reqpkt = pkt; 1058 sa->sa_radreq->rr_sa = sa; 1059 sa->sa_radreq->rr_ntry = 0; 1060 1061 iked_radius_request_send(env, sa->sa_radreq); 1062 1063 return 0; 1064} 1065 1066void 1067iked_radius_request_free(struct iked *env, struct iked_radserver_req *req) 1068{ 1069 if (req == NULL) 1070 return; 1071 timer_del(env, &req->rr_timer); 1072 free(req->rr_user); 1073 ibuf_free(req->rr_state); 1074 if (req->rr_reqpkt) 1075 radius_delete_packet(req->rr_reqpkt); 1076 if (req->rr_sa) 1077 req->rr_sa->sa_radreq = NULL; 1078 if (req->rr_server) 1079 TAILQ_REMOVE(&req->rr_server->rs_reqs, req, rr_entry); 1080 free(req); 1081} 1082 1083void 1084iked_radius_on_event(int fd, short ev, void *ctx) 1085{ 1086 struct iked *env; 1087 struct iked_radserver *server = ctx; 1088 struct iked_radserver_req *req; 1089 const struct iked_radcfgmap *cfgmap; 1090 RADIUS_PACKET *pkt; 1091 int i, resid; 1092 struct ibuf *e; 1093 const void *attrval; 1094 size_t attrlen; 1095 uint8_t code; 1096 char username[256]; 1097 u_char eapmsk[128]; 1098 /* RFC 3748 defines the MSK minimum size is 64 bytes */ 1099 size_t eapmsksiz = sizeof(eapmsk); 1100 1101 env = server->rs_env; 1102 pkt = radius_recv(server->rs_sock, 0); 1103 if (pkt == NULL) { 1104 log_info("%s: receiving a RADIUS message failed: %s", __func__, 1105 strerror(errno)); 1106 return; 1107 } 1108 resid = radius_get_id(pkt); 1109 1110 TAILQ_FOREACH(req, &server->rs_reqs, rr_entry) { 1111 if (req->rr_reqid == resid) 1112 break; 1113 } 1114 if (req == NULL) { 1115 log_debug("%s: received an unknown RADIUS message: id=%u", 1116 __func__, (unsigned)resid); 1117 return; 1118 } 1119 1120 radius_set_request_packet(pkt, req->rr_reqpkt); 1121 if (radius_check_response_authenticator(pkt, server->rs_secret) != 0) { 1122 log_info("%s: received an invalid RADIUS message: bad " 1123 "response authenticator", __func__); 1124 return; 1125 } 1126 if (req->rr_accounting) { 1127 /* accounting */ 1128 code = radius_get_code(pkt); 1129 switch (code) { 1130 case RADIUS_CODE_ACCOUNTING_RESPONSE: /* Expected */ 1131 break; 1132 default: 1133 log_info("%s: received an invalid RADIUS message: " 1134 "code %u", __func__, (unsigned)code); 1135 } 1136 timer_del(env, &req->rr_timer); 1137 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 1138 req->rr_server = NULL; 1139 free(req); 1140 return; 1141 } 1142 1143 /* authentication */ 1144 if (radius_check_message_authenticator(pkt, server->rs_secret) != 0) { 1145 log_info("%s: received an invalid RADIUS message: bad " 1146 "message authenticator", __func__); 1147 return; 1148 } 1149 1150 timer_del(env, &req->rr_timer); 1151 req->rr_ntry = 0; 1152 1153 if (req->rr_sa == NULL) 1154 goto fail; 1155 1156 code = radius_get_code(pkt); 1157 switch (code) { 1158 case RADIUS_CODE_ACCESS_CHALLENGE: 1159 if (radius_get_raw_attr_ptr(pkt, RADIUS_TYPE_STATE, &attrval, 1160 &attrlen) != 0) { 1161 log_info("%s: received an invalid RADIUS message: no " 1162 "state attribute", __func__); 1163 goto fail; 1164 } 1165 if ((req->rr_state != NULL && 1166 ibuf_set(req->rr_state, 0, attrval, attrlen) != 0) || 1167 (req->rr_state = ibuf_new(attrval, attrlen)) == NULL) { 1168 log_info("%s: ibuf_new() failed: %s", __func__, 1169 strerror(errno)); 1170 goto fail; 1171 } 1172 break; 1173 case RADIUS_CODE_ACCESS_ACCEPT: 1174 log_info("%s: received Access-Accept for %s", 1175 SPI_SA(req->rr_sa, __func__), req->rr_user); 1176 /* Try to retrieve the EAP MSK from the RADIUS response */ 1177 if (radius_get_eap_msk(pkt, eapmsk, &eapmsksiz, 1178 server->rs_secret) == 0) { 1179 ibuf_free(req->rr_sa->sa_eapmsk); 1180 if ((req->rr_sa->sa_eapmsk = ibuf_new(eapmsk, 1181 eapmsksiz)) == NULL) { 1182 log_info("%s: ibuf_new() failed: %s", __func__, 1183 strerror(errno)); 1184 goto fail; 1185 } 1186 } else 1187 log_debug("Could not retrieve the EAP MSK from the " 1188 "RADIUS message"); 1189 1190 free(req->rr_sa->sa_eapid); 1191 /* The EAP identity might be protected (RFC 3748 7.3) */ 1192 if (radius_get_string_attr(pkt, RADIUS_TYPE_USER_NAME, 1193 username, sizeof(username)) == 0 && 1194 strcmp(username, req->rr_user) != 0) { 1195 /* 1196 * The Access-Accept might have a User-Name. It 1197 * should be used for Accouting (RFC 2865 5.1). 1198 */ 1199 free(req->rr_user); 1200 req->rr_sa->sa_eapid = strdup(username); 1201 } else 1202 req->rr_sa->sa_eapid = req->rr_user; 1203 req->rr_user = NULL; 1204 1205 sa_state(env, req->rr_sa, IKEV2_STATE_AUTH_SUCCESS); 1206 1207 /* Map RADIUS attributes to cp */ 1208 if (TAILQ_EMPTY(&env->sc_radcfgmaps)) { 1209 for (i = 0; radius_cfgmaps[i].cfg_type != 0; i++) { 1210 cfgmap = &radius_cfgmaps[i]; 1211 iked_radius_config(req, pkt, cfgmap->cfg_type, 1212 cfgmap->vendor_id, cfgmap->attr_type); 1213 } 1214 } else { 1215 TAILQ_FOREACH(cfgmap, &env->sc_radcfgmaps, entry) 1216 iked_radius_config(req, pkt, cfgmap->cfg_type, 1217 cfgmap->vendor_id, cfgmap->attr_type); 1218 } 1219 1220 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 1221 req->rr_server = NULL; 1222 break; 1223 case RADIUS_CODE_ACCESS_REJECT: 1224 log_info("%s: received Access-Reject for %s", 1225 SPI_SA(req->rr_sa, __func__), req->rr_user); 1226 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 1227 req->rr_server = NULL; 1228 break; 1229 default: 1230 log_debug("%s: received an invalid RADIUS message: code %u", 1231 __func__, (unsigned)code); 1232 break; 1233 } 1234 1235 /* get the length first */ 1236 if (radius_get_raw_attr_cat(pkt, RADIUS_TYPE_EAP_MESSAGE, NULL, 1237 &attrlen) != 0) { 1238 log_info("%s: failed to retrieve the EAP message", __func__); 1239 goto fail; 1240 } 1241 /* allocate a buffer */ 1242 if ((e = ibuf_new(NULL, attrlen)) == NULL) { 1243 log_info("%s: ibuf_new() failed: %s", __func__, 1244 strerror(errno)); 1245 goto fail; 1246 } 1247 /* copy the message to the buffer */ 1248 if (radius_get_raw_attr_cat(pkt, RADIUS_TYPE_EAP_MESSAGE, 1249 ibuf_data(e), &attrlen) != 0) { 1250 ibuf_free(e); 1251 log_info("%s: failed to retrieve the EAP message", __func__); 1252 goto fail; 1253 } 1254 ikev2_send_ike_e(env, req->rr_sa, e, IKEV2_PAYLOAD_EAP, 1255 IKEV2_EXCHANGE_IKE_AUTH, 1); 1256 return; 1257 fail: 1258 if (req->rr_server != NULL) 1259 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 1260 req->rr_server = NULL; 1261 if (req->rr_sa != NULL) { 1262 ikev2_ike_sa_setreason(req->rr_sa, "RADIUS request failed"); 1263 sa_free(env, req->rr_sa); 1264 } 1265} 1266 1267void 1268iked_radius_request_send(struct iked *env, void *ctx) 1269{ 1270 struct iked_radserver_req *req = ctx, *req0; 1271 struct iked_radserver *server = req->rr_server; 1272 const int timeouts[] = { 2, 4, 8 }; 1273 uint8_t seq; 1274 int i, max_tries, max_failovers; 1275 struct sockaddr_storage ss; 1276 socklen_t sslen; 1277 struct iked_radservers *radservers; 1278 struct timespec now; 1279 1280 if (!req->rr_accounting) { 1281 max_tries = env->sc_radauth.max_tries; 1282 max_failovers = env->sc_radauth.max_failovers; 1283 radservers = &env->sc_radauthservers; 1284 } else { 1285 max_tries = env->sc_radacct.max_tries; 1286 max_failovers = env->sc_radacct.max_failovers; 1287 radservers = &env->sc_radacctservers; 1288 } 1289 1290 if (req->rr_ntry > max_tries) { 1291 req->rr_ntry = 0; 1292 log_info("%s: RADIUS server %s failed", __func__, 1293 print_addr(&server->rs_sockaddr)); 1294 next_server: 1295 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 1296 req->rr_server = NULL; 1297 if (req->rr_nfailover >= max_failovers || 1298 TAILQ_NEXT(server, rs_entry) == NULL) { 1299 log_info("%s: No more RADIUS server", __func__); 1300 goto fail; 1301 } else if (req->rr_state != NULL) { 1302 log_info("%s: Can't change RADIUS server: " 1303 "client has a state already", __func__); 1304 goto fail; 1305 } else { 1306 TAILQ_REMOVE(radservers, server, rs_entry); 1307 TAILQ_INSERT_TAIL(radservers, server, rs_entry); 1308 server = TAILQ_FIRST(radservers); 1309 log_info("%s: RADIUS server %s is active", 1310 __func__, print_addr(&server->rs_sockaddr)); 1311 } 1312 req->rr_nfailover++; 1313 } 1314 1315 if (req->rr_server != NULL && 1316 req->rr_server != TAILQ_FIRST(radservers)) { 1317 /* Current server is marked fail */ 1318 if (req->rr_state != NULL || req->rr_nfailover >= max_failovers) 1319 goto fail; /* can't fail over */ 1320 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 1321 req->rr_server = NULL; 1322 req->rr_nfailover++; 1323 } 1324 1325 if (req->rr_server == NULL) { 1326 /* Select a new server */ 1327 server = TAILQ_FIRST(radservers); 1328 if (server == NULL) { 1329 log_info("%s: No RADIUS server is configured", 1330 __func__); 1331 goto fail; 1332 } 1333 TAILQ_INSERT_TAIL(&server->rs_reqs, req, rr_entry); 1334 req->rr_server = server; 1335 1336 /* Prepare NAS-IP-Address */ 1337 if (server->rs_nas_ipv4.s_addr == INADDR_ANY && 1338 IN6_IS_ADDR_UNSPECIFIED(&server->rs_nas_ipv6)) { 1339 sslen = sizeof(ss); 1340 if (getsockname(server->rs_sock, (struct sockaddr *)&ss, 1341 &sslen) == 0) { 1342 if (ss.ss_family == AF_INET) 1343 server->rs_nas_ipv4 = 1344 ((struct sockaddr_in *)&ss) 1345 ->sin_addr; 1346 else 1347 server->rs_nas_ipv6 = 1348 ((struct sockaddr_in6 *)&ss) 1349 ->sin6_addr; 1350 } 1351 } 1352 } 1353 if (req->rr_ntry == 0) { 1354 /* decide the ID */ 1355 seq = ++server->rs_reqseq; 1356 for (i = 0; i < UCHAR_MAX; i++) { 1357 TAILQ_FOREACH(req0, &server->rs_reqs, rr_entry) { 1358 if (req0->rr_reqid == seq) 1359 break; 1360 } 1361 if (req0 == NULL) 1362 break; 1363 seq++; 1364 } 1365 if (i >= UCHAR_MAX) { 1366 log_info("%s: RADIUS server %s failed. Too many " 1367 "pending requests", __func__, 1368 print_addr(&server->rs_sockaddr)); 1369 if (TAILQ_NEXT(server, rs_entry) != NULL) 1370 goto next_server; 1371 goto fail; 1372 } 1373 req->rr_reqid = seq; 1374 radius_set_id(req->rr_reqpkt, req->rr_reqid); 1375 } 1376 1377 if (server->rs_nas_ipv4.s_addr != INADDR_ANY) 1378 radius_put_ipv4_attr(req->rr_reqpkt, RADIUS_TYPE_NAS_IP_ADDRESS, 1379 server->rs_nas_ipv4); 1380 else if (!IN6_IS_ADDR_UNSPECIFIED(&server->rs_nas_ipv6)) 1381 radius_put_ipv6_attr(req->rr_reqpkt, 1382 RADIUS_TYPE_NAS_IPV6_ADDRESS, &server->rs_nas_ipv6); 1383 /* Identifier */ 1384 radius_put_string_attr(req->rr_reqpkt, RADIUS_TYPE_NAS_IDENTIFIER, 1385 "OpenIKED"); 1386 1387 if (req->rr_accounting) { 1388 if (req->rr_ntry == 0 && req->rr_nfailover == 0) 1389 radius_put_uint32_attr(req->rr_reqpkt, 1390 RADIUS_TYPE_ACCT_DELAY_TIME, 0); 1391 else { 1392 clock_gettime(CLOCK_MONOTONIC, &now); 1393 timespecsub(&now, &req->rr_accttime, &now); 1394 radius_put_uint32_attr(req->rr_reqpkt, 1395 RADIUS_TYPE_ACCT_DELAY_TIME, now.tv_sec); 1396 } 1397 radius_set_accounting_request_authenticator(req->rr_reqpkt, 1398 server->rs_secret); 1399 } else { 1400 radius_put_message_authenticator(req->rr_reqpkt, 1401 server->rs_secret); 1402 } 1403 1404 if (radius_send(server->rs_sock, req->rr_reqpkt, 0) < 0) 1405 log_info("%s: sending a RADIUS message failed: %s", __func__, 1406 strerror(errno)); 1407 1408 if (req->rr_ntry >= (int)nitems(timeouts)) 1409 timer_add(env, &req->rr_timer, timeouts[nitems(timeouts) - 1]); 1410 else 1411 timer_add(env, &req->rr_timer, timeouts[req->rr_ntry]); 1412 req->rr_ntry++; 1413 return; 1414 fail: 1415 if (req->rr_server != NULL) 1416 TAILQ_REMOVE(&server->rs_reqs, req, rr_entry); 1417 req->rr_server = NULL; 1418 if (req->rr_sa != NULL) { 1419 ikev2_ike_sa_setreason(req->rr_sa, "RADIUS request failed"); 1420 sa_free(env, req->rr_sa); 1421 } 1422} 1423 1424void 1425iked_radius_fill_attributes(struct iked_sa *sa, RADIUS_PACKET *pkt) 1426{ 1427 /* NAS Port Type = Virtual */ 1428 radius_put_uint32_attr(pkt, 1429 RADIUS_TYPE_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_VIRTUAL); 1430 /* Service Type = Framed */ 1431 radius_put_uint32_attr(pkt, RADIUS_TYPE_SERVICE_TYPE, 1432 RADIUS_SERVICE_TYPE_FRAMED); 1433 /* Tunnel Type = EAP */ 1434 radius_put_uint32_attr(pkt, RADIUS_TYPE_TUNNEL_TYPE, 1435 RADIUS_TUNNEL_TYPE_ESP); 1436 1437 radius_put_string_attr(pkt, RADIUS_TYPE_CALLED_STATION_ID, 1438 print_addr(&sa->sa_local.addr)); 1439 radius_put_string_attr(pkt, RADIUS_TYPE_CALLING_STATION_ID, 1440 print_addr(&sa->sa_peer.addr)); 1441} 1442 1443void 1444iked_radius_config(struct iked_radserver_req *req, const RADIUS_PACKET *pkt, 1445 int cfg_type, uint32_t vendor_id, uint8_t attr_type) 1446{ 1447 unsigned int i; 1448 struct iked_sa *sa = req->rr_sa; 1449 struct in_addr ia4; 1450 struct in6_addr ia6; 1451 struct sockaddr_in *sin4; 1452 struct sockaddr_in6 *sin6; 1453 struct iked_addr *addr; 1454 struct iked_cfg *ikecfg; 1455 1456 for (i = 0; i < sa->sa_policy->pol_ncfg; i++) { 1457 ikecfg = &sa->sa_policy->pol_cfg[i]; 1458 if (ikecfg->cfg_type == cfg_type && 1459 ikecfg->cfg_type != IKEV2_CFG_INTERNAL_IP4_ADDRESS) 1460 return; /* use config rather than radius */ 1461 } 1462 switch (cfg_type) { 1463 case IKEV2_CFG_INTERNAL_IP4_ADDRESS: 1464 case IKEV2_CFG_INTERNAL_IP4_NETMASK: 1465 case IKEV2_CFG_INTERNAL_IP4_DNS: 1466 case IKEV2_CFG_INTERNAL_IP4_NBNS: 1467 case IKEV2_CFG_INTERNAL_IP4_DHCP: 1468 case IKEV2_CFG_INTERNAL_IP4_SERVER: 1469 if (vendor_id == 0 && radius_has_attr(pkt, attr_type)) 1470 radius_get_ipv4_attr(pkt, attr_type, &ia4); 1471 else if (vendor_id != 0 && radius_has_vs_attr(pkt, vendor_id, 1472 attr_type)) 1473 radius_get_vs_ipv4_attr(pkt, vendor_id, attr_type, 1474 &ia4); 1475 else 1476 break; /* no attribute contained */ 1477 1478 if (cfg_type == IKEV2_CFG_INTERNAL_IP4_NETMASK) { 1479 /* 1480 * This assumes IKEV2_CFG_INTERNAL_IP4_ADDRESS is 1481 * called before IKEV2_CFG_INTERNAL_IP4_NETMASK 1482 */ 1483 if (sa->sa_rad_addr == NULL) { 1484 /* 1485 * RFC 7296, IKEV2_CFG_INTERNAL_IP4_NETMASK 1486 * must be used with 1487 * IKEV2_CFG_INTERNAL_IP4_ADDRESS 1488 */ 1489 break; 1490 } 1491 if (ia4.s_addr == 0) { 1492 log_debug("%s: netmask is wrong", __func__); 1493 break; 1494 } 1495 if (ia4.s_addr == htonl(0)) 1496 sa->sa_rad_addr->addr_mask = 0; 1497 else 1498 sa->sa_rad_addr->addr_mask = 1499 33 - ffs(ntohl(ia4.s_addr)); 1500 if (sa->sa_rad_addr->addr_mask < 32) 1501 sa->sa_rad_addr->addr_net = 1; 1502 } 1503 if (cfg_type == IKEV2_CFG_INTERNAL_IP4_ADDRESS) { 1504 if ((addr = calloc(1, sizeof(*addr))) == NULL) { 1505 log_warn("%s: calloc", __func__); 1506 return; 1507 } 1508 sa->sa_rad_addr = addr; 1509 } else { 1510 req->rr_cfg[req->rr_ncfg].cfg_action = IKEV2_CP_REPLY; 1511 req->rr_cfg[req->rr_ncfg].cfg_type = cfg_type; 1512 addr = &req->rr_cfg[req->rr_ncfg].cfg.address; 1513 req->rr_ncfg++; 1514 } 1515 addr->addr_af = AF_INET; 1516 sin4 = (struct sockaddr_in *)&addr->addr; 1517 sin4->sin_family = AF_INET; 1518 sin4->sin_len = sizeof(struct sockaddr_in); 1519 sin4->sin_addr = ia4; 1520 break; 1521 case IKEV2_CFG_INTERNAL_IP6_ADDRESS: 1522 case IKEV2_CFG_INTERNAL_IP6_DNS: 1523 case IKEV2_CFG_INTERNAL_IP6_NBNS: 1524 case IKEV2_CFG_INTERNAL_IP6_DHCP: 1525 case IKEV2_CFG_INTERNAL_IP6_SERVER: 1526 if (vendor_id == 0 && radius_has_attr(pkt, attr_type)) 1527 radius_get_ipv6_attr(pkt, attr_type, &ia6); 1528 else if (vendor_id != 0 && radius_has_vs_attr(pkt, vendor_id, 1529 attr_type)) 1530 radius_get_vs_ipv6_attr(pkt, vendor_id, attr_type, 1531 &ia6); 1532 else 1533 break; /* no attribute contained */ 1534 1535 if (cfg_type == IKEV2_CFG_INTERNAL_IP6_ADDRESS) { 1536 if ((addr = calloc(1, sizeof(*addr))) == NULL) { 1537 log_warn("%s: calloc", __func__); 1538 return; 1539 } 1540 sa->sa_rad_addr = addr; 1541 } else { 1542 req->rr_cfg[req->rr_ncfg].cfg_action = IKEV2_CP_REPLY; 1543 req->rr_cfg[req->rr_ncfg].cfg_type = cfg_type; 1544 addr = &req->rr_cfg[req->rr_ncfg].cfg.address; 1545 req->rr_ncfg++; 1546 } 1547 addr->addr_af = AF_INET; 1548 sin6 = (struct sockaddr_in6 *)&addr->addr; 1549 sin6->sin6_family = AF_INET6; 1550 sin6->sin6_len = sizeof(struct sockaddr_in6); 1551 sin6->sin6_addr = ia6; 1552 break; 1553 } 1554 return; 1555} 1556 1557void 1558iked_radius_acct_on(struct iked *env) 1559{ 1560 if (TAILQ_EMPTY(&env->sc_radacctservers)) 1561 return; 1562 if (env->sc_radaccton == 0) { /* trigger once */ 1563 iked_radius_acct_request(env, NULL, 1564 RADIUS_ACCT_STATUS_TYPE_ACCT_ON); 1565 env->sc_radaccton = 1; 1566 } 1567} 1568 1569void 1570iked_radius_acct_off(struct iked *env) 1571{ 1572 iked_radius_acct_request(env, NULL, RADIUS_ACCT_STATUS_TYPE_ACCT_OFF); 1573} 1574 1575void 1576iked_radius_acct_start(struct iked *env, struct iked_sa *sa) 1577{ 1578 iked_radius_acct_request(env, sa, RADIUS_ACCT_STATUS_TYPE_START); 1579} 1580 1581void 1582iked_radius_acct_stop(struct iked *env, struct iked_sa *sa) 1583{ 1584 iked_radius_acct_request(env, sa, RADIUS_ACCT_STATUS_TYPE_STOP); 1585} 1586 1587void 1588iked_radius_acct_request(struct iked *env, struct iked_sa *sa, uint8_t stype) 1589{ 1590 struct iked_radserver_req *req; 1591 RADIUS_PACKET *pkt; 1592 struct iked_addr *addr4 = NULL; 1593 struct iked_addr *addr6 = NULL; 1594 struct in_addr mask4; 1595 char sa_id[IKED_ID_SIZE]; 1596 char sid[16 + 1]; 1597 struct timespec now; 1598 int cause; 1599 1600 if (TAILQ_EMPTY(&env->sc_radacctservers)) 1601 return; 1602 /* 1603 * In RFC2866 5.6, "Users who are delivered service without 1604 * being authenticated SHOULD NOT generate Accounting records 1605 */ 1606 if (sa != NULL && sa->sa_eapid == NULL) { 1607 /* fallback to IKEID for accounting */ 1608 if (ikev2_print_id(IKESA_DSTID(sa), sa_id, sizeof(sa_id)) != -1) 1609 sa->sa_eapid = strdup(sa_id); 1610 if (sa->sa_eapid == NULL) 1611 return; 1612 } 1613 1614 if ((req = calloc(1, sizeof(struct iked_radserver_req))) == NULL) { 1615 log_debug("%s: calloc faile for iked_radserver_req: %s", 1616 __func__, strerror(errno)); 1617 return; 1618 } 1619 req->rr_accounting = 1; 1620 clock_gettime(CLOCK_MONOTONIC, &now); 1621 req->rr_accttime = now; 1622 timer_set(env, &req->rr_timer, iked_radius_request_send, req); 1623 1624 if ((pkt = radius_new_request_packet(RADIUS_CODE_ACCOUNTING_REQUEST)) 1625 == NULL) { 1626 log_debug("%s: radius_new_request_packet failed %s", __func__, 1627 strerror(errno)); 1628 return; 1629 } 1630 1631 /* RFC 2866 5.1. Acct-Status-Type */ 1632 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_STATUS_TYPE, stype); 1633 1634 if (sa == NULL) { 1635 /* ASSERT(stype == RADIUS_ACCT_STATUS_TYPE_ACCT_ON || 1636 stype == RADIUS_ACCT_STATUS_TYPE_ACCT_OFF) */ 1637 req->rr_reqpkt = pkt; 1638 req->rr_ntry = 0; 1639 iked_radius_request_send(env, req); 1640 return; 1641 } 1642 1643 iked_radius_fill_attributes(sa, pkt); 1644 1645 radius_put_string_attr(pkt, RADIUS_TYPE_USER_NAME, sa->sa_eapid); 1646 1647 /* RFC 2866 5.5. Acct-Session-Id */ 1648 snprintf(sid, sizeof(sid), "%016llx", 1649 (unsigned long long)sa->sa_hdr.sh_ispi); 1650 radius_put_string_attr(pkt, RADIUS_TYPE_ACCT_SESSION_ID, sid); 1651 1652 /* Accounting Request must have Framed-IP-Address */ 1653 addr4 = sa->sa_addrpool; 1654 if (addr4 != NULL) { 1655 radius_put_ipv4_attr(pkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, 1656 ((struct sockaddr_in *)&addr4->addr)->sin_addr); 1657 if (addr4->addr_mask != 0) { 1658 mask4.s_addr = htonl( 1659 0xFFFFFFFFUL << (32 - addr4->addr_mask)); 1660 radius_put_ipv4_attr(pkt, 1661 RADIUS_TYPE_FRAMED_IP_NETMASK, mask4); 1662 } 1663 } 1664 addr6 = sa->sa_addrpool6; 1665 if (addr6 != NULL) 1666 radius_put_ipv6_attr(pkt, RADIUS_TYPE_FRAMED_IPV6_ADDRESS, 1667 &((struct sockaddr_in6 *)&addr6->addr)->sin6_addr); 1668 1669 /* RFC2866 5.6 Acct-Authentic */ 1670 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_AUTHENTIC, 1671 (sa->sa_radreq != NULL)? RADIUS_ACCT_AUTHENTIC_RADIUS : 1672 RADIUS_ACCT_AUTHENTIC_LOCAL); 1673 1674 switch (stype) { 1675 case RADIUS_ACCT_STATUS_TYPE_START: 1676 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_STATUS_TYPE, 1677 RADIUS_ACCT_STATUS_TYPE_START); 1678 break; 1679 case RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE: 1680 case RADIUS_ACCT_STATUS_TYPE_STOP: 1681 /* RFC 2866 5.7. Acct-Session-Time */ 1682 timespecsub(&now, &sa->sa_starttime, &now); 1683 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_SESSION_TIME, 1684 now.tv_sec); 1685 /* RFC 2866 5.10 Acct-Terminate-Cause */ 1686 cause = RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL; 1687 if (sa->sa_reason) { 1688 if (strcmp(sa->sa_reason, "received delete") == 0) { 1689 cause = RADIUS_TERMNATE_CAUSE_USER_REQUEST; 1690 } else if (strcmp(sa->sa_reason, "SA rekeyed") == 0) { 1691 cause = RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT; 1692 } else if (strncmp(sa->sa_reason, "retransmit", 1693 strlen("retransmit")) == 0) { 1694 cause = RADIUS_TERMNATE_CAUSE_LOST_SERVICE; 1695 } else if (strcmp(sa->sa_reason, 1696 "disconnect requested") == 0) { 1697 cause = RADIUS_TERMNATE_CAUSE_ADMIN_RESET; 1698 } 1699 } 1700 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_TERMINATE_CAUSE, 1701 cause); 1702 /* I/O statistics {Input,Output}-{Packets,Octets,Gigawords} */ 1703 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_INPUT_PACKETS, 1704 sa->sa_stats.sas_ipackets); 1705 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS, 1706 sa->sa_stats.sas_opackets); 1707 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_INPUT_OCTETS, 1708 sa->sa_stats.sas_ibytes & 0xffffffffUL); 1709 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_OUTPUT_OCTETS, 1710 sa->sa_stats.sas_obytes & 0xffffffffUL); 1711 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, 1712 sa->sa_stats.sas_ibytes >> 32); 1713 radius_put_uint32_attr(pkt, RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS, 1714 sa->sa_stats.sas_obytes >> 32); 1715 break; 1716 } 1717 req->rr_reqpkt = pkt; 1718 req->rr_ntry = 0; 1719 iked_radius_request_send(env, req); 1720} 1721 1722void 1723iked_radius_dae_on_event(int fd, short ev, void *ctx) 1724{ 1725 struct iked_raddae *dae = ctx; 1726 struct iked *env = dae->rd_env; 1727 RADIUS_PACKET *req = NULL, *res = NULL; 1728 struct sockaddr_storage ss; 1729 socklen_t sslen; 1730 struct iked_radclient *client; 1731 struct iked_sa *sa = NULL; 1732 char attr[256], *endp, *reason; 1733 const char *cp; 1734 int code, n = 0; 1735 uint64_t ispi = 0; 1736 uint32_t u32, cause = 0; 1737 struct iked_addr *addr4 = NULL; 1738 1739 reason = "disconnect requested"; 1740 1741 sslen = sizeof(ss); 1742 req = radius_recvfrom(dae->rd_sock, 0, (struct sockaddr *)&ss, &sslen); 1743 if (req == NULL) { 1744 log_warn("%s: receiving a RADIUS message failed: %s", __func__, 1745 strerror(errno)); 1746 return; 1747 } 1748 TAILQ_FOREACH(client, &env->sc_raddaeclients, rc_entry) { 1749 if (sockaddr_cmp((struct sockaddr *)&client->rc_sockaddr, 1750 (struct sockaddr *)&ss, -1) == 0) 1751 break; 1752 } 1753 if (client == NULL) { 1754 log_warnx("%s: received RADIUS message from %s: " 1755 "unknown client", __func__, print_addr(&ss)); 1756 goto out; 1757 } 1758 1759 if (radius_check_accounting_request_authenticator(req, 1760 client->rc_secret) != 0) { 1761 log_warnx("%s: received an invalid RADIUS message from %s: bad " 1762 "response authenticator", __func__, print_addr(&ss)); 1763 goto out; 1764 } 1765 1766 if ((code = radius_get_code(req)) != RADIUS_CODE_DISCONNECT_REQUEST) { 1767 /* Code other than Disconnect-Request is not supported */ 1768 if (code == RADIUS_CODE_COA_REQUEST) { 1769 log_info("received CoA-Request from %s", 1770 print_addr(&ss)); 1771 code = RADIUS_CODE_COA_NAK; 1772 cause = RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED; 1773 goto send; 1774 } 1775 log_warnx("%s: received an invalid RADIUS message " 1776 "from %s: unknown code %d", __func__, 1777 print_addr(&ss), code); 1778 goto out; 1779 } 1780 1781 log_info("received Disconnect-Request from %s", print_addr(&ss)); 1782 1783 if (radius_get_string_attr(req, RADIUS_TYPE_ACCT_SESSION_ID, attr, 1784 sizeof(attr)) == 0) { 1785 ispi = strtoull(attr, &endp, 16); 1786 if (attr[0] != '\0' && *endp == '\0' && errno != ERANGE && 1787 ispi != ULLONG_MAX) { 1788 RB_FOREACH(sa, iked_sas, &env->sc_sas) { 1789 if (sa->sa_hdr.sh_ispi == ispi) { 1790 ikev2_ike_sa_setreason(sa, reason); 1791 ikev2_ike_sa_delete(env, sa); 1792 n++; 1793 } 1794 } 1795 } 1796 } 1797 if (radius_get_string_attr(req, RADIUS_TYPE_USER_NAME, attr, 1798 sizeof(attr)) == 0) { 1799 RB_FOREACH(sa, iked_sas, &env->sc_sas) { 1800 if (sa->sa_eapid != NULL && 1801 strcmp(sa->sa_eapid, attr) == 0) { 1802 ikev2_ike_sa_setreason(sa, reason); 1803 ikev2_ike_sa_delete(env, sa); 1804 n++; 1805 } 1806 } 1807 } 1808 if (radius_get_uint32_attr(req, RADIUS_TYPE_FRAMED_IP_ADDRESS, &u32) 1809 == 0) { 1810 addr4 = sa->sa_addrpool; 1811 if (addr4 != NULL) { 1812 RB_FOREACH(sa, iked_sas, &env->sc_sas) { 1813 if (u32 == ((struct sockaddr_in *)&addr4->addr) 1814 ->sin_addr.s_addr) { 1815 ikev2_ike_sa_setreason(sa, reason); 1816 ikev2_ike_sa_delete(env, sa); 1817 n++; 1818 } 1819 } 1820 } 1821 } 1822 if (radius_get_string_attr(req, RADIUS_TYPE_CALLED_STATION_ID, attr, 1823 sizeof(attr)) != 0) { 1824 RB_FOREACH(sa, iked_sas, &env->sc_sas) { 1825 cp = print_addr(&sa->sa_local.addr); 1826 if (strcmp(cp, attr) == 0) { 1827 ikev2_ike_sa_setreason(sa, reason); 1828 ikev2_ike_sa_delete(env, sa); 1829 n++; 1830 } 1831 } 1832 } 1833 if (radius_get_string_attr(req, RADIUS_TYPE_CALLING_STATION_ID, attr, 1834 sizeof(attr)) != 0) { 1835 RB_FOREACH(sa, iked_sas, &env->sc_sas) { 1836 cp = print_addr(&sa->sa_peer.addr); 1837 if (strcmp(cp, attr) == 0) { 1838 ikev2_ike_sa_setreason(sa, reason); 1839 ikev2_ike_sa_delete(env, sa); 1840 n++; 1841 } 1842 } 1843 } 1844 1845 if (n > 0) 1846 code = RADIUS_CODE_DISCONNECT_ACK; 1847 else { 1848 code = RADIUS_CODE_DISCONNECT_ACK; 1849 cause = RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND; 1850 } 1851 send: 1852 res = radius_new_response_packet(code, req); 1853 if (res == NULL) { 1854 log_warn("%s: radius_new_response_packet", __func__); 1855 goto out; 1856 } 1857 radius_set_response_authenticator(res, client->rc_secret); 1858 if (cause != 0) 1859 radius_put_uint32_attr(res, RADIUS_TYPE_ERROR_CAUSE, cause); 1860 if (radius_sendto(dae->rd_sock, res, 0, (struct sockaddr *)&ss, sslen) 1861 == -1) 1862 log_warn("%s: sendto", __func__); 1863 log_info("send %s for %s", 1864 (code == RADIUS_CODE_DISCONNECT_ACK)? "Disconnect-ACK" : 1865 (code == RADIUS_CODE_DISCONNECT_NAK)? "Disconnect-NAK" : "CoA-NAK", 1866 print_addr(&ss)); 1867 out: 1868 radius_delete_packet(req); 1869 if (res != NULL) 1870 radius_delete_packet(res); 1871} 1872