1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright 1999 Internet Business Solutions Ltd., Switzerland 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 * 30 */ 31 32 #include <stdint.h> 33 #include <sys/param.h> 34 35 #include <sys/select.h> 36 #include <sys/socket.h> 37 #include <netinet/in_systm.h> 38 #include <netinet/in.h> 39 #include <netinet/ip.h> 40 #include <arpa/inet.h> 41 #include <sys/un.h> 42 #include <net/route.h> 43 44 #ifdef LOCALRAD 45 #include "radlib.h" 46 #include "radlib_vs.h" 47 #else 48 #include <radlib.h> 49 #include <radlib_vs.h> 50 #endif 51 52 #include <errno.h> 53 #ifndef NODES 54 #include <md5.h> 55 #endif 56 #include <stdarg.h> 57 #include <stdio.h> 58 #include <stdlib.h> 59 #include <string.h> 60 #include <sys/time.h> 61 #include <termios.h> 62 #include <unistd.h> 63 #include <netdb.h> 64 65 #include "layer.h" 66 #include "defs.h" 67 #include "log.h" 68 #include "descriptor.h" 69 #include "prompt.h" 70 #include "timer.h" 71 #include "fsm.h" 72 #include "iplist.h" 73 #include "slcompress.h" 74 #include "throughput.h" 75 #include "lqr.h" 76 #include "hdlc.h" 77 #include "mbuf.h" 78 #include "ncpaddr.h" 79 #include "ip.h" 80 #include "ipcp.h" 81 #include "ipv6cp.h" 82 #include "route.h" 83 #include "command.h" 84 #include "filter.h" 85 #include "lcp.h" 86 #include "ccp.h" 87 #include "link.h" 88 #include "mp.h" 89 #include "radius.h" 90 #include "auth.h" 91 #include "async.h" 92 #include "physical.h" 93 #include "chat.h" 94 #include "cbcp.h" 95 #include "chap.h" 96 #include "datalink.h" 97 #include "ncp.h" 98 #include "bundle.h" 99 #include "proto.h" 100 #include "iface.h" 101 102 #ifndef NODES 103 struct mschap_response { 104 u_char ident; 105 u_char flags; 106 u_char lm_response[24]; 107 u_char nt_response[24]; 108 }; 109 110 struct mschap2_response { 111 u_char ident; 112 u_char flags; 113 u_char pchallenge[16]; 114 u_char reserved[8]; 115 u_char response[24]; 116 }; 117 118 #define AUTH_LEN 16 119 #define SALT_LEN 2 120 #endif 121 122 static const char * 123 radius_policyname(int policy) 124 { 125 switch(policy) { 126 case MPPE_POLICY_ALLOWED: 127 return "Allowed"; 128 case MPPE_POLICY_REQUIRED: 129 return "Required"; 130 } 131 return NumStr(policy, NULL, 0); 132 } 133 134 static const char * 135 radius_typesname(int types) 136 { 137 switch(types) { 138 case MPPE_TYPE_40BIT: 139 return "40 bit"; 140 case MPPE_TYPE_128BIT: 141 return "128 bit"; 142 case MPPE_TYPE_40BIT|MPPE_TYPE_128BIT: 143 return "40 or 128 bit"; 144 } 145 return NumStr(types, NULL, 0); 146 } 147 148 #ifndef NODES 149 static void 150 demangle(struct radius *r, const void *mangled, size_t mlen, 151 char **buf, size_t *len) 152 { 153 char R[AUTH_LEN]; /* variable names as per rfc2548 */ 154 const char *S; 155 u_char b[16]; 156 const u_char *A, *C; 157 MD5_CTX Context; 158 int Slen, i, Clen, Ppos; 159 u_char *P; 160 161 if (mlen % 16 != SALT_LEN) { 162 log_Printf(LogWARN, "Cannot interpret mangled data of length %ld\n", 163 (u_long)mlen); 164 *buf = NULL; 165 *len = 0; 166 return; 167 } 168 169 /* We need the RADIUS Request-Authenticator */ 170 if (rad_request_authenticator(r->cx.rad, R, sizeof R) != AUTH_LEN) { 171 log_Printf(LogWARN, "Cannot obtain the RADIUS request authenticator\n"); 172 *buf = NULL; 173 *len = 0; 174 return; 175 } 176 177 A = (const u_char *)mangled; /* Salt comes first */ 178 C = (const u_char *)mangled + SALT_LEN; /* Then the ciphertext */ 179 Clen = mlen - SALT_LEN; 180 S = rad_server_secret(r->cx.rad); /* We need the RADIUS secret */ 181 Slen = strlen(S); 182 P = alloca(Clen); /* We derive our plaintext */ 183 184 MD5Init(&Context); 185 MD5Update(&Context, S, Slen); 186 MD5Update(&Context, R, AUTH_LEN); 187 MD5Update(&Context, A, SALT_LEN); 188 MD5Final(b, &Context); 189 Ppos = 0; 190 191 while (Clen) { 192 Clen -= 16; 193 194 for (i = 0; i < 16; i++) 195 P[Ppos++] = C[i] ^ b[i]; 196 197 if (Clen) { 198 MD5Init(&Context); 199 MD5Update(&Context, S, Slen); 200 MD5Update(&Context, C, 16); 201 MD5Final(b, &Context); 202 } 203 204 C += 16; 205 } 206 207 /* 208 * The resulting plain text consists of a one-byte length, the text and 209 * maybe some padding. 210 */ 211 *len = *P; 212 if (*len > mlen - 1) { 213 log_Printf(LogWARN, "Mangled data seems to be garbage\n"); 214 *buf = NULL; 215 *len = 0; 216 return; 217 } 218 219 if ((*buf = malloc(*len)) == NULL) { 220 log_Printf(LogWARN, "demangle: Out of memory (%lu bytes)\n", (u_long)*len); 221 *len = 0; 222 } else 223 memcpy(*buf, P + 1, *len); 224 } 225 #endif 226 227 /* XXX: This should go into librarius. */ 228 #ifndef NOINET6 229 static uint8_t * 230 rad_cvt_ipv6prefix(const void *data, size_t len) 231 { 232 const size_t ipv6len = sizeof(struct in6_addr) + 2; 233 uint8_t *s; 234 235 if (len > ipv6len) 236 return NULL; 237 s = malloc(ipv6len); 238 if (s != NULL) { 239 memset(s, 0, ipv6len); 240 memcpy(s, data, len); 241 } 242 return s; 243 } 244 #endif 245 246 /* 247 * rad_continue_send_request() has given us `got' (non-zero). Deal with it. 248 */ 249 static void 250 radius_Process(struct radius *r, int got) 251 { 252 char *argv[MAXARGS], *nuke; 253 struct bundle *bundle; 254 int argc, addrs, res, width; 255 size_t len; 256 struct ncprange dest; 257 struct ncpaddr gw; 258 const void *data; 259 const char *stype; 260 u_int32_t ipaddr, vendor; 261 struct in_addr ip; 262 #ifndef NOINET6 263 uint8_t ipv6addr[INET6_ADDRSTRLEN]; 264 struct in6_addr ip6; 265 #endif 266 267 r->cx.fd = -1; /* Stop select()ing */ 268 stype = r->cx.auth ? "auth" : "acct"; 269 270 switch (got) { 271 case RAD_ACCESS_ACCEPT: 272 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 273 "Radius(%s): ACCEPT received\n", stype); 274 if (!r->cx.auth) { 275 rad_close(r->cx.rad); 276 return; 277 } 278 break; 279 280 case RAD_ACCESS_REJECT: 281 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 282 "Radius(%s): REJECT received\n", stype); 283 if (!r->cx.auth) { 284 rad_close(r->cx.rad); 285 return; 286 } 287 break; 288 289 case RAD_ACCESS_CHALLENGE: 290 /* we can't deal with this (for now) ! */ 291 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 292 "Radius: CHALLENGE received (can't handle yet)\n"); 293 if (r->cx.auth) 294 auth_Failure(r->cx.auth); 295 rad_close(r->cx.rad); 296 return; 297 298 case RAD_ACCOUNTING_RESPONSE: 299 /* 300 * It's probably not ideal to log this at PHASE level as we'll see 301 * too much stuff going to the log when ``set rad_alive'' is used. 302 * So we differ from older behaviour (ppp version 3.1 and before) 303 * and just log accounting responses to LogRADIUS. 304 */ 305 log_Printf(LogRADIUS, "Radius(%s): Accounting response received\n", 306 stype); 307 if (r->cx.auth) 308 auth_Failure(r->cx.auth); /* unexpected !!! */ 309 310 /* No further processing for accounting requests, please */ 311 rad_close(r->cx.rad); 312 return; 313 314 case -1: 315 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 316 "radius(%s): %s\n", stype, rad_strerror(r->cx.rad)); 317 if (r->cx.auth) 318 auth_Failure(r->cx.auth); 319 rad_close(r->cx.rad); 320 return; 321 322 default: 323 log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype, 324 got, rad_strerror(r->cx.rad)); 325 if (r->cx.auth) 326 auth_Failure(r->cx.auth); 327 rad_close(r->cx.rad); 328 return; 329 } 330 331 /* Let's see what we've got in our reply */ 332 r->ip.s_addr = r->mask.s_addr = INADDR_NONE; 333 r->mtu = 0; 334 r->vj = 0; 335 while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) { 336 switch (res) { 337 case RAD_FRAMED_IP_ADDRESS: 338 r->ip = rad_cvt_addr(data); 339 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 340 " IP %s\n", inet_ntoa(r->ip)); 341 break; 342 343 case RAD_FILTER_ID: 344 free(r->filterid); 345 if ((r->filterid = rad_cvt_string(data, len)) == NULL) { 346 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 347 auth_Failure(r->cx.auth); 348 rad_close(r->cx.rad); 349 return; 350 } 351 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 352 " Filter \"%s\"\n", r->filterid); 353 break; 354 355 case RAD_SESSION_TIMEOUT: 356 r->sessiontime = rad_cvt_int(data); 357 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 358 " Session-Timeout %lu\n", r->sessiontime); 359 break; 360 361 case RAD_FRAMED_IP_NETMASK: 362 r->mask = rad_cvt_addr(data); 363 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 364 " Netmask %s\n", inet_ntoa(r->mask)); 365 break; 366 367 case RAD_FRAMED_MTU: 368 r->mtu = rad_cvt_int(data); 369 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 370 " MTU %lu\n", r->mtu); 371 break; 372 373 case RAD_FRAMED_ROUTING: 374 /* Disabled for now - should we automatically set up some filters ? */ 375 /* rad_cvt_int(data); */ 376 /* bit 1 = Send routing packets */ 377 /* bit 2 = Receive routing packets */ 378 break; 379 380 case RAD_FRAMED_COMPRESSION: 381 r->vj = rad_cvt_int(data) == 1 ? 1 : 0; 382 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 383 " VJ %sabled\n", r->vj ? "en" : "dis"); 384 break; 385 386 case RAD_FRAMED_ROUTE: 387 /* 388 * We expect a string of the format ``dest[/bits] gw [metrics]'' 389 * Any specified metrics are ignored. MYADDR and HISADDR are 390 * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same 391 * as ``HISADDR''. 392 */ 393 394 if ((nuke = rad_cvt_string(data, len)) == NULL) { 395 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 396 auth_Failure(r->cx.auth); 397 rad_close(r->cx.rad); 398 return; 399 } 400 401 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 402 " Route: %s\n", nuke); 403 bundle = r->cx.auth->physical->dl->bundle; 404 ip.s_addr = INADDR_ANY; 405 ncpaddr_setip4(&gw, ip); 406 ncprange_setip4host(&dest, ip); 407 argc = command_Interpret(nuke, strlen(nuke), argv); 408 if (argc < 0) 409 log_Printf(LogWARN, "radius: %s: Syntax error\n", 410 argc == 1 ? argv[0] : "\"\""); 411 else if (argc < 2) 412 log_Printf(LogWARN, "radius: %s: Invalid route\n", 413 argc == 1 ? argv[0] : "\"\""); 414 else if ((strcasecmp(argv[0], "default") != 0 && 415 !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 416 !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 417 log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 418 argv[0], argv[1]); 419 else { 420 ncprange_getwidth(&dest, &width); 421 if (width == 32 && strchr(argv[0], '/') == NULL) { 422 /* No mask specified - use the natural mask */ 423 ncprange_getip4addr(&dest, &ip); 424 ncprange_setip4mask(&dest, addr2mask(ip)); 425 } 426 addrs = 0; 427 428 if (!strncasecmp(argv[0], "HISADDR", 7)) 429 addrs = ROUTE_DSTHISADDR; 430 else if (!strncasecmp(argv[0], "MYADDR", 6)) 431 addrs = ROUTE_DSTMYADDR; 432 433 if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) { 434 addrs |= ROUTE_GWHISADDR; 435 ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip); 436 } else if (strcasecmp(argv[1], "HISADDR") == 0) 437 addrs |= ROUTE_GWHISADDR; 438 439 route_Add(&r->routes, addrs, &dest, &gw); 440 } 441 free(nuke); 442 break; 443 444 case RAD_REPLY_MESSAGE: 445 free(r->repstr); 446 if ((r->repstr = rad_cvt_string(data, len)) == NULL) { 447 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 448 auth_Failure(r->cx.auth); 449 rad_close(r->cx.rad); 450 return; 451 } 452 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 453 " Reply-Message \"%s\"\n", r->repstr); 454 break; 455 456 #ifndef NOINET6 457 case RAD_FRAMED_IPV6_PREFIX: 458 free(r->ipv6prefix); 459 if ((r->ipv6prefix = rad_cvt_ipv6prefix(data, len)) == NULL) { 460 log_Printf(LogERROR, "rad_cvt_ipv6prefix: %s\n", 461 "Malformed attribute in response"); 462 auth_Failure(r->cx.auth); 463 rad_close(r->cx.rad); 464 return; 465 } 466 inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr)); 467 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 468 " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]); 469 break; 470 471 case RAD_FRAMED_IPV6_ROUTE: 472 /* 473 * We expect a string of the format ``dest[/bits] gw [metrics]'' 474 * Any specified metrics are ignored. MYADDR6 and HISADDR6 are 475 * understood for ``dest'' and ``gw'' and ``::'' is the same 476 * as ``HISADDR6''. 477 */ 478 479 if ((nuke = rad_cvt_string(data, len)) == NULL) { 480 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 481 auth_Failure(r->cx.auth); 482 rad_close(r->cx.rad); 483 return; 484 } 485 486 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 487 " IPv6 Route: %s\n", nuke); 488 bundle = r->cx.auth->physical->dl->bundle; 489 ncpaddr_setip6(&gw, &in6addr_any); 490 ncprange_set(&dest, &gw, 0); 491 argc = command_Interpret(nuke, strlen(nuke), argv); 492 if (argc < 0) 493 log_Printf(LogWARN, "radius: %s: Syntax error\n", 494 argc == 1 ? argv[0] : "\"\""); 495 else if (argc < 2) 496 log_Printf(LogWARN, "radius: %s: Invalid route\n", 497 argc == 1 ? argv[0] : "\"\""); 498 else if ((strcasecmp(argv[0], "default") != 0 && 499 !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 500 !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 501 log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 502 argv[0], argv[1]); 503 else { 504 addrs = 0; 505 506 if (!strncasecmp(argv[0], "HISADDR6", 8)) 507 addrs = ROUTE_DSTHISADDR6; 508 else if (!strncasecmp(argv[0], "MYADDR6", 7)) 509 addrs = ROUTE_DSTMYADDR6; 510 511 if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) { 512 addrs |= ROUTE_GWHISADDR6; 513 ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr); 514 } else if (strcasecmp(argv[1], "HISADDR6") == 0) 515 addrs |= ROUTE_GWHISADDR6; 516 517 route_Add(&r->ipv6routes, addrs, &dest, &gw); 518 } 519 free(nuke); 520 break; 521 #endif 522 523 case RAD_VENDOR_SPECIFIC: 524 if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) { 525 log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n", 526 rad_strerror(r->cx.rad)); 527 auth_Failure(r->cx.auth); 528 rad_close(r->cx.rad); 529 return; 530 } 531 532 switch (vendor) { 533 case RAD_VENDOR_MICROSOFT: 534 switch (res) { 535 #ifndef NODES 536 case RAD_MICROSOFT_MS_CHAP_ERROR: 537 free(r->errstr); 538 if (len == 0) 539 r->errstr = NULL; 540 else { 541 if (len < 3 || ((const char *)data)[1] != '=') { 542 /* 543 * Only point at the String field if we don't think the 544 * peer has misformatted the response. 545 */ 546 data = (const char *)data + 1; 547 len--; 548 } else 549 log_Printf(LogWARN, "Warning: The MS-CHAP-Error " 550 "attribute is mis-formatted. Compensating\n"); 551 if ((r->errstr = rad_cvt_string((const char *)data, 552 len)) == NULL) { 553 log_Printf(LogERROR, "rad_cvt_string: %s\n", 554 rad_strerror(r->cx.rad)); 555 auth_Failure(r->cx.auth); 556 rad_close(r->cx.rad); 557 return; 558 } 559 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 560 " MS-CHAP-Error \"%s\"\n", r->errstr); 561 } 562 break; 563 564 case RAD_MICROSOFT_MS_CHAP2_SUCCESS: 565 free(r->msrepstr); 566 if (len == 0) 567 r->msrepstr = NULL; 568 else { 569 if (len < 3 || ((const char *)data)[1] != '=') { 570 /* 571 * Only point at the String field if we don't think the 572 * peer has misformatted the response. 573 */ 574 data = (const char *)data + 1; 575 len--; 576 } else 577 log_Printf(LogWARN, "Warning: The MS-CHAP2-Success " 578 "attribute is mis-formatted. Compensating\n"); 579 if ((r->msrepstr = rad_cvt_string((const char *)data, 580 len)) == NULL) { 581 log_Printf(LogERROR, "rad_cvt_string: %s\n", 582 rad_strerror(r->cx.rad)); 583 auth_Failure(r->cx.auth); 584 rad_close(r->cx.rad); 585 return; 586 } 587 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 588 " MS-CHAP2-Success \"%s\"\n", r->msrepstr); 589 } 590 break; 591 592 case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY: 593 r->mppe.policy = rad_cvt_int(data); 594 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 595 " MS-MPPE-Encryption-Policy %s\n", 596 radius_policyname(r->mppe.policy)); 597 break; 598 599 case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES: 600 r->mppe.types = rad_cvt_int(data); 601 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 602 " MS-MPPE-Encryption-Types %s\n", 603 radius_typesname(r->mppe.types)); 604 break; 605 606 case RAD_MICROSOFT_MS_MPPE_RECV_KEY: 607 free(r->mppe.recvkey); 608 demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen); 609 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 610 " MS-MPPE-Recv-Key ********\n"); 611 break; 612 613 case RAD_MICROSOFT_MS_MPPE_SEND_KEY: 614 demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen); 615 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 616 " MS-MPPE-Send-Key ********\n"); 617 break; 618 #endif 619 620 default: 621 log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific " 622 "RADIUS attribute %d\n", res); 623 break; 624 } 625 break; 626 627 default: 628 log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n", 629 (unsigned long)vendor, res); 630 break; 631 } 632 break; 633 634 default: 635 log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res); 636 break; 637 } 638 } 639 640 if (res == -1) { 641 log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n", 642 rad_strerror(r->cx.rad)); 643 auth_Failure(r->cx.auth); 644 } else if (got == RAD_ACCESS_REJECT) 645 auth_Failure(r->cx.auth); 646 else { 647 r->valid = 1; 648 auth_Success(r->cx.auth); 649 } 650 rad_close(r->cx.rad); 651 } 652 653 /* 654 * We've either timed out or select()ed on the read descriptor 655 */ 656 static void 657 radius_Continue(struct radius *r, int sel) 658 { 659 struct timeval tv; 660 int got; 661 662 timer_Stop(&r->cx.timer); 663 if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) { 664 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 665 "Radius: Request re-sent\n"); 666 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 667 timer_Start(&r->cx.timer); 668 return; 669 } 670 671 radius_Process(r, got); 672 } 673 674 /* 675 * Time to call rad_continue_send_request() - timed out. 676 */ 677 static void 678 radius_Timeout(void *v) 679 { 680 radius_Continue((struct radius *)v, 0); 681 } 682 683 /* 684 * Time to call rad_continue_send_request() - something to read. 685 */ 686 static void 687 radius_Read(struct fdescriptor *d, struct bundle *bundle __unused, 688 const fd_set *fdset __unused) 689 { 690 radius_Continue(descriptor2radius(d), 1); 691 } 692 693 /* 694 * Flush any pending transactions 695 */ 696 void 697 radius_Flush(struct radius *r) 698 { 699 struct timeval tv; 700 fd_set s; 701 702 while (r->cx.fd != -1) { 703 FD_ZERO(&s); 704 FD_SET(r->cx.fd, &s); 705 tv.tv_sec = 0; 706 tv.tv_usec = TICKUNIT; 707 select(r->cx.fd + 1, &s, NULL, NULL, &tv); 708 radius_Continue(r, 1); 709 } 710 } 711 712 /* 713 * Behave as a struct fdescriptor (descriptor.h) 714 */ 715 static int 716 radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w __unused, 717 fd_set *e __unused, int *n) 718 { 719 struct radius *rad = descriptor2radius(d); 720 721 if (r && rad->cx.fd != -1) { 722 FD_SET(rad->cx.fd, r); 723 if (*n < rad->cx.fd + 1) 724 *n = rad->cx.fd + 1; 725 log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd); 726 return 1; 727 } 728 729 return 0; 730 } 731 732 /* 733 * Behave as a struct fdescriptor (descriptor.h) 734 */ 735 static int 736 radius_IsSet(struct fdescriptor *d, const fd_set *fdset) 737 { 738 struct radius *r = descriptor2radius(d); 739 740 return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset); 741 } 742 743 /* 744 * Behave as a struct fdescriptor (descriptor.h) 745 */ 746 static int 747 radius_Write(struct fdescriptor *d __unused, struct bundle *bundle __unused, 748 const fd_set *fdset __unused) 749 { 750 /* We never want to write here ! */ 751 log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n"); 752 return 0; 753 } 754 755 /* 756 * Initialise ourselves 757 */ 758 void 759 radius_Init(struct radius *r) 760 { 761 r->desc.type = RADIUS_DESCRIPTOR; 762 r->desc.UpdateSet = radius_UpdateSet; 763 r->desc.IsSet = radius_IsSet; 764 r->desc.Read = radius_Read; 765 r->desc.Write = radius_Write; 766 r->cx.fd = -1; 767 r->cx.rad = NULL; 768 memset(&r->cx.timer, '\0', sizeof r->cx.timer); 769 r->cx.auth = NULL; 770 r->valid = 0; 771 r->vj = 0; 772 r->ip.s_addr = INADDR_ANY; 773 r->mask.s_addr = INADDR_NONE; 774 r->routes = NULL; 775 r->mtu = DEF_MTU; 776 r->msrepstr = NULL; 777 r->repstr = NULL; 778 #ifndef NOINET6 779 r->ipv6prefix = NULL; 780 r->ipv6routes = NULL; 781 #endif 782 r->errstr = NULL; 783 r->mppe.policy = 0; 784 r->mppe.types = 0; 785 r->mppe.recvkey = NULL; 786 r->mppe.recvkeylen = 0; 787 r->mppe.sendkey = NULL; 788 r->mppe.sendkeylen = 0; 789 *r->cfg.file = '\0'; 790 log_Printf(LogDEBUG, "Radius: radius_Init\n"); 791 } 792 793 /* 794 * Forget everything and go back to initialised state. 795 */ 796 void 797 radius_Destroy(struct radius *r) 798 { 799 r->valid = 0; 800 log_Printf(LogDEBUG, "Radius: radius_Destroy\n"); 801 timer_Stop(&r->cx.timer); 802 route_DeleteAll(&r->routes); 803 #ifndef NOINET6 804 route_DeleteAll(&r->ipv6routes); 805 #endif 806 free(r->filterid); 807 r->filterid = NULL; 808 free(r->msrepstr); 809 r->msrepstr = NULL; 810 free(r->repstr); 811 r->repstr = NULL; 812 #ifndef NOINET6 813 free(r->ipv6prefix); 814 r->ipv6prefix = NULL; 815 #endif 816 free(r->errstr); 817 r->errstr = NULL; 818 free(r->mppe.recvkey); 819 r->mppe.recvkey = NULL; 820 r->mppe.recvkeylen = 0; 821 free(r->mppe.sendkey); 822 r->mppe.sendkey = NULL; 823 r->mppe.sendkeylen = 0; 824 if (r->cx.fd != -1) { 825 r->cx.fd = -1; 826 rad_close(r->cx.rad); 827 } 828 } 829 830 static int 831 radius_put_physical_details(struct radius *rad, struct physical *p) 832 { 833 int slot, type; 834 835 type = RAD_VIRTUAL; 836 if (p->handler) 837 switch (p->handler->type) { 838 case I4B_DEVICE: 839 type = RAD_ISDN_SYNC; 840 break; 841 842 case TTY_DEVICE: 843 type = RAD_ASYNC; 844 break; 845 846 case ETHER_DEVICE: 847 type = RAD_ETHERNET; 848 break; 849 850 case TCP_DEVICE: 851 case UDP_DEVICE: 852 case EXEC_DEVICE: 853 case ATM_DEVICE: 854 case NG_DEVICE: 855 type = RAD_VIRTUAL; 856 break; 857 } 858 859 if (rad_put_int(rad->cx.rad, RAD_NAS_PORT_TYPE, type) != 0) { 860 log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad->cx.rad)); 861 rad_close(rad->cx.rad); 862 return 0; 863 } 864 865 switch (rad->port_id_type) { 866 case RPI_PID: 867 slot = (int)getpid(); 868 break; 869 case RPI_IFNUM: 870 slot = p->dl->bundle->iface->index; 871 break; 872 case RPI_TUNNUM: 873 slot = p->dl->bundle->unit; 874 break; 875 case RPI_DEFAULT: 876 default: 877 slot = physical_Slot(p); 878 break; 879 } 880 881 if (slot >= 0) 882 if (rad_put_int(rad->cx.rad, RAD_NAS_PORT, slot) != 0) { 883 log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad->cx.rad)); 884 rad_close(rad->cx.rad); 885 return 0; 886 } 887 888 return 1; 889 } 890 891 /* 892 * Start an authentication request to the RADIUS server. 893 */ 894 int 895 radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, 896 const char *key, int klen, const char *nchallenge, 897 int nclen) 898 { 899 char hostname[MAXHOSTNAMELEN]; 900 struct timeval tv; 901 const char *what = "questionable"; /* silence warnings! */ 902 char *mac_addr; 903 int got; 904 struct hostent *hp; 905 struct in_addr hostaddr; 906 #ifndef NODES 907 struct mschap_response msresp; 908 struct mschap2_response msresp2; 909 const struct MSCHAPv2_resp *keyv2; 910 #endif 911 912 if (!*r->cfg.file) 913 return 0; 914 915 if (r->cx.fd != -1) 916 /* 917 * We assume that our name/key/challenge is the same as last time, 918 * and just continue to wait for the RADIUS server(s). 919 */ 920 return 1; 921 922 radius_Destroy(r); 923 924 if ((r->cx.rad = rad_auth_open()) == NULL) { 925 log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 926 return 0; 927 } 928 929 if (rad_config(r->cx.rad, r->cfg.file) != 0) { 930 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 931 rad_close(r->cx.rad); 932 return 0; 933 } 934 935 if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) { 936 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 937 rad_close(r->cx.rad); 938 return 0; 939 } 940 941 if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 || 942 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 943 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 944 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 945 rad_close(r->cx.rad); 946 return 0; 947 } 948 949 switch (authp->physical->link.lcp.want_auth) { 950 case PROTO_PAP: 951 /* We're talking PAP */ 952 if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) { 953 log_Printf(LogERROR, "PAP: rad_put_string: %s\n", 954 rad_strerror(r->cx.rad)); 955 rad_close(r->cx.rad); 956 return 0; 957 } 958 what = "PAP"; 959 break; 960 961 case PROTO_CHAP: 962 switch (authp->physical->link.lcp.want_authtype) { 963 case 0x5: 964 if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 || 965 rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) { 966 log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", 967 rad_strerror(r->cx.rad)); 968 rad_close(r->cx.rad); 969 return 0; 970 } 971 what = "CHAP"; 972 break; 973 974 #ifndef NODES 975 case 0x80: 976 if (klen != 50) { 977 log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen); 978 rad_close(r->cx.rad); 979 return 0; 980 } 981 982 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 983 RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 984 msresp.ident = *key; 985 msresp.flags = 0x01; 986 memcpy(msresp.lm_response, key + 1, 24); 987 memcpy(msresp.nt_response, key + 25, 24); 988 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 989 RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp, 990 sizeof msresp); 991 what = "MSCHAP"; 992 break; 993 994 case 0x81: 995 if (klen != sizeof(*keyv2) + 1) { 996 log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen); 997 rad_close(r->cx.rad); 998 return 0; 999 } 1000 1001 keyv2 = (const struct MSCHAPv2_resp *)(key + 1); 1002 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 1003 RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 1004 msresp2.ident = *key; 1005 msresp2.flags = keyv2->Flags; 1006 memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response); 1007 memset(msresp2.reserved, '\0', sizeof msresp2.reserved); 1008 memcpy(msresp2.pchallenge, keyv2->PeerChallenge, 1009 sizeof msresp2.pchallenge); 1010 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 1011 RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2, 1012 sizeof msresp2); 1013 what = "MSCHAPv2"; 1014 break; 1015 #endif 1016 default: 1017 log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n", 1018 authp->physical->link.lcp.want_authtype); 1019 rad_close(r->cx.rad); 1020 return 0; 1021 } 1022 } 1023 1024 if (gethostname(hostname, sizeof hostname) != 0) 1025 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 1026 else { 1027 if (Enabled(authp->physical->dl->bundle, OPT_NAS_IP_ADDRESS) && 1028 (hp = gethostbyname(hostname)) != NULL) { 1029 hostaddr.s_addr = *(u_long *)hp->h_addr; 1030 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 1031 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1032 rad_strerror(r->cx.rad)); 1033 rad_close(r->cx.rad); 1034 return 0; 1035 } 1036 } 1037 if (Enabled(authp->physical->dl->bundle, OPT_NAS_IDENTIFIER) && 1038 rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 1039 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1040 rad_strerror(r->cx.rad)); 1041 rad_close(r->cx.rad); 1042 return 0; 1043 } 1044 } 1045 1046 if ((mac_addr = getenv("HISMACADDR")) != NULL && 1047 rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) { 1048 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1049 rad_close(r->cx.rad); 1050 return 0; 1051 } 1052 1053 radius_put_physical_details(r, authp->physical); 1054 1055 log_Printf(LogRADIUS, "Radius(auth): %s data sent for %s\n", what, name); 1056 1057 r->cx.auth = authp; 1058 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 1059 radius_Process(r, got); 1060 else { 1061 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 1062 "Radius: Request sent\n"); 1063 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 1064 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 1065 r->cx.timer.func = radius_Timeout; 1066 r->cx.timer.name = "radius auth"; 1067 r->cx.timer.arg = r; 1068 timer_Start(&r->cx.timer); 1069 } 1070 1071 return 1; 1072 } 1073 1074 /* Fetch IP, netmask from IPCP */ 1075 void 1076 radius_Account_Set_Ip(struct radacct *ac, struct in_addr *peer_ip, 1077 struct in_addr *netmask) 1078 { 1079 ac->proto = PROTO_IPCP; 1080 memcpy(&ac->peer.ip.addr, peer_ip, sizeof(ac->peer.ip.addr)); 1081 memcpy(&ac->peer.ip.mask, netmask, sizeof(ac->peer.ip.mask)); 1082 } 1083 1084 #ifndef NOINET6 1085 /* Fetch interface-id from IPV6CP */ 1086 void 1087 radius_Account_Set_Ipv6(struct radacct *ac, u_char *ifid) 1088 { 1089 ac->proto = PROTO_IPV6CP; 1090 memcpy(&ac->peer.ipv6.ifid, ifid, sizeof(ac->peer.ipv6.ifid)); 1091 } 1092 #endif 1093 1094 /* 1095 * Send an accounting request to the RADIUS server 1096 */ 1097 void 1098 radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl, 1099 int acct_type, struct pppThroughput *stats) 1100 { 1101 struct timeval tv; 1102 int got; 1103 char hostname[MAXHOSTNAMELEN]; 1104 char *mac_addr; 1105 struct hostent *hp; 1106 struct in_addr hostaddr; 1107 1108 if (!*r->cfg.file) 1109 return; 1110 1111 if (r->cx.fd != -1) 1112 /* 1113 * We assume that our name/key/challenge is the same as last time, 1114 * and just continue to wait for the RADIUS server(s). 1115 */ 1116 return; 1117 1118 timer_Stop(&r->cx.timer); 1119 1120 if ((r->cx.rad = rad_acct_open()) == NULL) { 1121 log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 1122 return; 1123 } 1124 1125 if (rad_config(r->cx.rad, r->cfg.file) != 0) { 1126 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 1127 rad_close(r->cx.rad); 1128 return; 1129 } 1130 1131 if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) { 1132 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 1133 rad_close(r->cx.rad); 1134 return; 1135 } 1136 1137 /* Grab some accounting data and initialize structure */ 1138 if (acct_type == RAD_START) { 1139 ac->rad_parent = r; 1140 /* Fetch username from datalink */ 1141 strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name); 1142 ac->user_name[AUTHLEN-1] = '\0'; 1143 1144 ac->authentic = 2; /* Assume RADIUS verified auth data */ 1145 1146 /* Generate a session ID */ 1147 snprintf(ac->session_id, sizeof ac->session_id, "%s%ld-%s%lu", 1148 dl->bundle->cfg.auth.name, (long)getpid(), 1149 dl->peer.authname, (unsigned long)stats->uptime); 1150 1151 /* And grab our MP socket name */ 1152 snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s", 1153 dl->bundle->ncp.mp.active ? 1154 dl->bundle->ncp.mp.server.socket.sun_path : ""); 1155 } 1156 1157 if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 || 1158 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 1159 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 1160 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1161 rad_close(r->cx.rad); 1162 return; 1163 } 1164 switch (ac->proto) { 1165 case PROTO_IPCP: 1166 if (rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS, 1167 ac->peer.ip.addr) != 0 || 1168 rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK, 1169 ac->peer.ip.mask) != 0) { 1170 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1171 rad_close(r->cx.rad); 1172 return; 1173 } 1174 break; 1175 #ifndef NOINET6 1176 case PROTO_IPV6CP: 1177 if (rad_put_attr(r->cx.rad, RAD_FRAMED_INTERFACE_ID, ac->peer.ipv6.ifid, 1178 sizeof(ac->peer.ipv6.ifid)) != 0) { 1179 log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad)); 1180 rad_close(r->cx.rad); 1181 return; 1182 } 1183 if (r->ipv6prefix) { 1184 /* 1185 * Since PPP doesn't delegate an IPv6 prefix to a peer, 1186 * Framed-IPv6-Prefix may be not used, actually. 1187 */ 1188 if (rad_put_attr(r->cx.rad, RAD_FRAMED_IPV6_PREFIX, r->ipv6prefix, 1189 sizeof(struct in6_addr) + 2) != 0) { 1190 log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad)); 1191 rad_close(r->cx.rad); 1192 return; 1193 } 1194 } 1195 break; 1196 #endif 1197 default: 1198 /* We don't log any protocol specific information */ 1199 break; 1200 } 1201 1202 if ((mac_addr = getenv("HISMACADDR")) != NULL && 1203 rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) { 1204 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1205 rad_close(r->cx.rad); 1206 return; 1207 } 1208 1209 if (gethostname(hostname, sizeof hostname) != 0) 1210 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 1211 else { 1212 if (Enabled(dl->bundle, OPT_NAS_IP_ADDRESS) && 1213 (hp = gethostbyname(hostname)) != NULL) { 1214 hostaddr.s_addr = *(u_long *)hp->h_addr; 1215 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 1216 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1217 rad_strerror(r->cx.rad)); 1218 rad_close(r->cx.rad); 1219 return; 1220 } 1221 } 1222 if (Enabled(dl->bundle, OPT_NAS_IDENTIFIER) && 1223 rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 1224 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1225 rad_strerror(r->cx.rad)); 1226 rad_close(r->cx.rad); 1227 return; 1228 } 1229 } 1230 1231 radius_put_physical_details(r, dl->physical); 1232 1233 if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 || 1234 rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 || 1235 rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID, 1236 ac->multi_session_id) != 0 || 1237 rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) { 1238 /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */ 1239 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1240 rad_close(r->cx.rad); 1241 return; 1242 } 1243 1244 if (acct_type == RAD_STOP || acct_type == RAD_ALIVE) 1245 /* Show some statistics */ 1246 if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn % UINT32_MAX) != 0 || 1247 rad_put_int(r->cx.rad, RAD_ACCT_INPUT_GIGAWORDS, stats->OctetsIn / UINT32_MAX) != 0 || 1248 rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 || 1249 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut % UINT32_MAX) != 0 || 1250 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_GIGAWORDS, stats->OctetsOut / UINT32_MAX) != 0 || 1251 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut) 1252 != 0 || 1253 rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats)) 1254 != 0) { 1255 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1256 rad_close(r->cx.rad); 1257 return; 1258 } 1259 1260 if (log_IsKept(LogPHASE) || log_IsKept(LogRADIUS)) { 1261 const char *what; 1262 int level; 1263 1264 switch (acct_type) { 1265 case RAD_START: 1266 what = "START"; 1267 level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1268 break; 1269 case RAD_STOP: 1270 what = "STOP"; 1271 level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1272 break; 1273 case RAD_ALIVE: 1274 what = "ALIVE"; 1275 level = LogRADIUS; 1276 break; 1277 default: 1278 what = "<unknown>"; 1279 level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1280 break; 1281 } 1282 log_Printf(level, "Radius(acct): %s data sent\n", what); 1283 } 1284 1285 r->cx.auth = NULL; /* Not valid for accounting requests */ 1286 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 1287 radius_Process(r, got); 1288 else { 1289 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 1290 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 1291 r->cx.timer.func = radius_Timeout; 1292 r->cx.timer.name = "radius acct"; 1293 r->cx.timer.arg = r; 1294 timer_Start(&r->cx.timer); 1295 } 1296 } 1297 1298 /* 1299 * How do things look at the moment ? 1300 */ 1301 void 1302 radius_Show(struct radius *r, struct prompt *p) 1303 { 1304 prompt_Printf(p, " Radius config: %s", 1305 *r->cfg.file ? r->cfg.file : "none"); 1306 if (r->valid) { 1307 prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip)); 1308 prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask)); 1309 prompt_Printf(p, " MTU: %lu\n", r->mtu); 1310 prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis"); 1311 prompt_Printf(p, " Message: %s\n", r->repstr ? r->repstr : ""); 1312 prompt_Printf(p, " MPPE Enc Policy: %s\n", 1313 radius_policyname(r->mppe.policy)); 1314 prompt_Printf(p, " MPPE Enc Types: %s\n", 1315 radius_typesname(r->mppe.types)); 1316 prompt_Printf(p, " MPPE Recv Key: %seceived\n", 1317 r->mppe.recvkey ? "R" : "Not r"); 1318 prompt_Printf(p, " MPPE Send Key: %seceived\n", 1319 r->mppe.sendkey ? "R" : "Not r"); 1320 prompt_Printf(p, " MS-CHAP2-Response: %s\n", 1321 r->msrepstr ? r->msrepstr : ""); 1322 prompt_Printf(p, " Error Message: %s\n", r->errstr ? r->errstr : ""); 1323 if (r->routes) 1324 route_ShowSticky(p, r->routes, " Routes", 16); 1325 #ifndef NOINET6 1326 if (r->ipv6routes) 1327 route_ShowSticky(p, r->ipv6routes, " IPv6 Routes", 16); 1328 #endif 1329 } else 1330 prompt_Printf(p, " (not authenticated)\n"); 1331 } 1332 1333 static void 1334 radius_alive(void *v) 1335 { 1336 struct bundle *bundle = (struct bundle *)v; 1337 1338 timer_Stop(&bundle->radius.alive.timer); 1339 bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS; 1340 if (bundle->radius.alive.timer.load) { 1341 radius_Account(&bundle->radius, &bundle->radacct, 1342 bundle->links, RAD_ALIVE, &bundle->ncp.ipcp.throughput); 1343 timer_Start(&bundle->radius.alive.timer); 1344 } 1345 } 1346 1347 void 1348 radius_StartTimer(struct bundle *bundle) 1349 { 1350 if (*bundle->radius.cfg.file && bundle->radius.alive.interval) { 1351 bundle->radius.alive.timer.func = radius_alive; 1352 bundle->radius.alive.timer.name = "radius alive"; 1353 bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS; 1354 bundle->radius.alive.timer.arg = bundle; 1355 radius_alive(bundle); 1356 } 1357 } 1358 1359 void 1360 radius_StopTimer(struct radius *r) 1361 { 1362 timer_Stop(&r->alive.timer); 1363 } 1364