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