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$ 27 * 28 */ 29 30 #include <sys/param.h> 31 #include <sys/socket.h> 32 #include <netinet/in_systm.h> 33 #include <netinet/in.h> 34 #include <netinet/ip.h> 35 #include <arpa/inet.h> 36 #include <sys/un.h> 37 #include <net/route.h> 38 39 #ifdef LOCALRAD 40 #include "radlib.h" 41 #include "radlib_vs.h" 42 #else 43 #include <radlib.h> 44 #include <radlib_vs.h> 45 #endif 46 47 #include <errno.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <sys/time.h> 52 #include <termios.h> 53 #include <unistd.h> 54 #include <netdb.h> 55 56 #include "layer.h" 57 #include "defs.h" 58 #include "log.h" 59 #include "descriptor.h" 60 #include "prompt.h" 61 #include "timer.h" 62 #include "fsm.h" 63 #include "iplist.h" 64 #include "slcompress.h" 65 #include "throughput.h" 66 #include "lqr.h" 67 #include "hdlc.h" 68 #include "mbuf.h" 69 #include "ncpaddr.h" 70 #include "ip.h" 71 #include "ipcp.h" 72 #include "ipv6cp.h" 73 #include "route.h" 74 #include "command.h" 75 #include "filter.h" 76 #include "lcp.h" 77 #include "ccp.h" 78 #include "link.h" 79 #include "mp.h" 80 #include "radius.h" 81 #include "auth.h" 82 #include "async.h" 83 #include "physical.h" 84 #include "chat.h" 85 #include "cbcp.h" 86 #include "chap.h" 87 #include "datalink.h" 88 #include "ncp.h" 89 #include "bundle.h" 90 #include "proto.h" 91 92 #ifndef NODES 93 struct mschap_response { 94 u_char ident; 95 u_char flags; 96 u_char lm_response[24]; 97 u_char nt_response[24]; 98 }; 99 100 struct mschap2_response { 101 u_char ident; 102 u_char flags; 103 u_char pchallenge[16]; 104 u_char reserved[8]; 105 u_char response[24]; 106 }; 107 #endif 108 109 /* 110 * rad_continue_send_request() has given us `got' (non-zero). Deal with it. 111 */ 112 static void 113 radius_Process(struct radius *r, int got) 114 { 115 char *argv[MAXARGS], *nuke; 116 struct bundle *bundle; 117 int argc, addrs, res, width; 118 size_t len; 119 struct ncprange dest; 120 struct ncpaddr gw; 121 const void *data; 122 const char *stype; 123 u_int32_t ipaddr, vendor; 124 struct in_addr ip; 125 126 r->cx.fd = -1; /* Stop select()ing */ 127 stype = r->cx.auth ? "auth" : "acct"; 128 129 switch (got) { 130 case RAD_ACCESS_ACCEPT: 131 log_Printf(LogPHASE, "Radius(%s): ACCEPT received\n", stype); 132 if (!r->cx.auth) { 133 rad_close(r->cx.rad); 134 return; 135 } 136 break; 137 138 case RAD_ACCESS_REJECT: 139 log_Printf(LogPHASE, "Radius(%s): REJECT received\n", stype); 140 if (!r->cx.auth) { 141 rad_close(r->cx.rad); 142 return; 143 } 144 break; 145 146 case RAD_ACCESS_CHALLENGE: 147 /* we can't deal with this (for now) ! */ 148 log_Printf(LogPHASE, "Radius: CHALLENGE received (can't handle yet)\n"); 149 if (r->cx.auth) 150 auth_Failure(r->cx.auth); 151 rad_close(r->cx.rad); 152 return; 153 154 case RAD_ACCOUNTING_RESPONSE: 155 log_Printf(LogPHASE, "Radius(%s): Accounting response received\n", stype); 156 if (r->cx.auth) 157 auth_Failure(r->cx.auth); /* unexpected !!! */ 158 159 /* No further processing for accounting requests, please */ 160 rad_close(r->cx.rad); 161 return; 162 163 case -1: 164 log_Printf(LogPHASE, "radius(%s): %s\n", stype, rad_strerror(r->cx.rad)); 165 if (r->cx.auth) 166 auth_Failure(r->cx.auth); 167 rad_close(r->cx.rad); 168 return; 169 170 default: 171 log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype, 172 got, rad_strerror(r->cx.rad)); 173 if (r->cx.auth) 174 auth_Failure(r->cx.auth); 175 rad_close(r->cx.rad); 176 return; 177 } 178 179 /* Let's see what we've got in our reply */ 180 r->ip.s_addr = r->mask.s_addr = INADDR_NONE; 181 r->mtu = 0; 182 r->vj = 0; 183 while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) { 184 switch (res) { 185 case RAD_FRAMED_IP_ADDRESS: 186 r->ip = rad_cvt_addr(data); 187 log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip)); 188 break; 189 190 case RAD_FILTER_ID: 191 free(r->filterid); 192 if ((r->filterid = rad_cvt_string(data, len)) == NULL) { 193 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 194 auth_Failure(r->cx.auth); 195 rad_close(r->cx.rad); 196 return; 197 } 198 log_Printf(LogPHASE, " Filter \"%s\"\n", r->filterid); 199 break; 200 201 case RAD_SESSION_TIMEOUT: 202 r->sessiontime = rad_cvt_int(data); 203 log_Printf(LogPHASE, " Session-Timeout %lu\n", r->sessiontime); 204 break; 205 206 case RAD_FRAMED_IP_NETMASK: 207 r->mask = rad_cvt_addr(data); 208 log_Printf(LogPHASE, " Netmask %s\n", inet_ntoa(r->mask)); 209 break; 210 211 case RAD_FRAMED_MTU: 212 r->mtu = rad_cvt_int(data); 213 log_Printf(LogPHASE, " MTU %lu\n", r->mtu); 214 break; 215 216 case RAD_FRAMED_ROUTING: 217 /* Disabled for now - should we automatically set up some filters ? */ 218 /* rad_cvt_int(data); */ 219 /* bit 1 = Send routing packets */ 220 /* bit 2 = Receive routing packets */ 221 break; 222 223 case RAD_FRAMED_COMPRESSION: 224 r->vj = rad_cvt_int(data) == 1 ? 1 : 0; 225 log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis"); 226 break; 227 228 case RAD_FRAMED_ROUTE: 229 /* 230 * We expect a string of the format ``dest[/bits] gw [metrics]'' 231 * Any specified metrics are ignored. MYADDR and HISADDR are 232 * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same 233 * as ``HISADDR''. 234 */ 235 236 if ((nuke = rad_cvt_string(data, len)) == NULL) { 237 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 238 auth_Failure(r->cx.auth); 239 rad_close(r->cx.rad); 240 return; 241 } 242 243 log_Printf(LogPHASE, " Route: %s\n", nuke); 244 bundle = r->cx.auth->physical->dl->bundle; 245 ip.s_addr = INADDR_ANY; 246 ncprange_setip4host(&dest, ip); 247 argc = command_Interpret(nuke, strlen(nuke), argv); 248 if (argc < 0) 249 log_Printf(LogWARN, "radius: %s: Syntax error\n", 250 argc == 1 ? argv[0] : "\"\""); 251 else if (argc < 2) 252 log_Printf(LogWARN, "radius: %s: Invalid route\n", 253 argc == 1 ? argv[0] : "\"\""); 254 else if ((strcasecmp(argv[0], "default") != 0 && 255 !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 256 !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 257 log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 258 argv[0], argv[1]); 259 else { 260 ncprange_getwidth(&dest, &width); 261 if (width == 32 && strchr(argv[0], '/') == NULL) { 262 /* No mask specified - use the natural mask */ 263 ncprange_getip4addr(&dest, &ip); 264 ncprange_setip4mask(&dest, addr2mask(ip)); 265 } 266 addrs = 0; 267 268 if (!strncasecmp(argv[0], "HISADDR", 7)) 269 addrs = ROUTE_DSTHISADDR; 270 else if (!strncasecmp(argv[0], "MYADDR", 6)) 271 addrs = ROUTE_DSTMYADDR; 272 273 if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) { 274 addrs |= ROUTE_GWHISADDR; 275 ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip); 276 } else if (strcasecmp(argv[1], "HISADDR") == 0) 277 addrs |= ROUTE_GWHISADDR; 278 279 route_Add(&r->routes, addrs, &dest, &gw); 280 } 281 free(nuke); 282 break; 283 284 case RAD_REPLY_MESSAGE: 285 free(r->repstr); 286 if ((r->repstr = rad_cvt_string(data, len)) == NULL) { 287 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 288 auth_Failure(r->cx.auth); 289 rad_close(r->cx.rad); 290 return; 291 } 292 log_Printf(LogPHASE, " Reply-Message \"%s\"\n", r->repstr); 293 break; 294 295 case RAD_VENDOR_SPECIFIC: 296 if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) { 297 log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n", 298 rad_strerror(r->cx.rad)); 299 auth_Failure(r->cx.auth); 300 rad_close(r->cx.rad); 301 return; 302 } 303 304 switch (vendor) { 305 case RAD_VENDOR_MICROSOFT: 306 switch (res) { 307 case RAD_MICROSOFT_MS_CHAP_ERROR: 308 free(r->errstr); 309 if ((r->errstr = rad_cvt_string(data, len)) == NULL) { 310 log_Printf(LogERROR, "rad_cvt_string: %s\n", 311 rad_strerror(r->cx.rad)); 312 auth_Failure(r->cx.auth); 313 rad_close(r->cx.rad); 314 return; 315 } 316 log_Printf(LogPHASE, " MS-CHAP-Error \"%s\"\n", r->errstr); 317 break; 318 319 case RAD_MICROSOFT_MS_CHAP2_SUCCESS: 320 free(r->msrepstr); 321 if ((r->msrepstr = rad_cvt_string(data, len)) == NULL) { 322 log_Printf(LogERROR, "rad_cvt_string: %s\n", 323 rad_strerror(r->cx.rad)); 324 auth_Failure(r->cx.auth); 325 rad_close(r->cx.rad); 326 return; 327 } 328 log_Printf(LogPHASE, " MS-CHAP2-Success \"%s\"\n", r->msrepstr); 329 break; 330 331 default: 332 log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific " 333 "RADIUS attribute %d\n", res); 334 break; 335 } 336 break; 337 338 default: 339 log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n", 340 (unsigned long)vendor, res); 341 break; 342 } 343 break; 344 345 default: 346 log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res); 347 break; 348 } 349 } 350 351 if (res == -1) { 352 log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n", 353 rad_strerror(r->cx.rad)); 354 auth_Failure(r->cx.auth); 355 } else if (got == RAD_ACCESS_REJECT) 356 auth_Failure(r->cx.auth); 357 else { 358 r->valid = 1; 359 auth_Success(r->cx.auth); 360 } 361 rad_close(r->cx.rad); 362 } 363 364 /* 365 * We've either timed out or select()ed on the read descriptor 366 */ 367 static void 368 radius_Continue(struct radius *r, int sel) 369 { 370 struct timeval tv; 371 int got; 372 373 timer_Stop(&r->cx.timer); 374 if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) { 375 log_Printf(LogPHASE, "Radius: Request re-sent\n"); 376 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 377 timer_Start(&r->cx.timer); 378 return; 379 } 380 381 radius_Process(r, got); 382 } 383 384 /* 385 * Time to call rad_continue_send_request() - timed out. 386 */ 387 static void 388 radius_Timeout(void *v) 389 { 390 radius_Continue((struct radius *)v, 0); 391 } 392 393 /* 394 * Time to call rad_continue_send_request() - something to read. 395 */ 396 static void 397 radius_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 398 { 399 radius_Continue(descriptor2radius(d), 1); 400 } 401 402 /* 403 * Behave as a struct fdescriptor (descriptor.h) 404 */ 405 static int 406 radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 407 { 408 struct radius *rad = descriptor2radius(d); 409 410 if (r && rad->cx.fd != -1) { 411 FD_SET(rad->cx.fd, r); 412 if (*n < rad->cx.fd + 1) 413 *n = rad->cx.fd + 1; 414 log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd); 415 return 1; 416 } 417 418 return 0; 419 } 420 421 /* 422 * Behave as a struct fdescriptor (descriptor.h) 423 */ 424 static int 425 radius_IsSet(struct fdescriptor *d, const fd_set *fdset) 426 { 427 struct radius *r = descriptor2radius(d); 428 429 return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset); 430 } 431 432 /* 433 * Behave as a struct fdescriptor (descriptor.h) 434 */ 435 static int 436 radius_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 437 { 438 /* We never want to write here ! */ 439 log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n"); 440 return 0; 441 } 442 443 /* 444 * Initialise ourselves 445 */ 446 void 447 radius_Init(struct radius *r) 448 { 449 r->desc.type = RADIUS_DESCRIPTOR; 450 r->desc.UpdateSet = radius_UpdateSet; 451 r->desc.IsSet = radius_IsSet; 452 r->desc.Read = radius_Read; 453 r->desc.Write = radius_Write; 454 r->cx.fd = -1; 455 r->cx.rad = NULL; 456 memset(&r->cx.timer, '\0', sizeof r->cx.timer); 457 r->cx.auth = NULL; 458 r->valid = 0; 459 r->vj = 0; 460 r->ip.s_addr = INADDR_ANY; 461 r->mask.s_addr = INADDR_NONE; 462 r->routes = NULL; 463 r->mtu = DEF_MTU; 464 r->msrepstr = NULL; 465 r->repstr = NULL; 466 r->errstr = NULL; 467 *r->cfg.file = '\0';; 468 log_Printf(LogDEBUG, "Radius: radius_Init\n"); 469 } 470 471 /* 472 * Forget everything and go back to initialised state. 473 */ 474 void 475 radius_Destroy(struct radius *r) 476 { 477 r->valid = 0; 478 log_Printf(LogDEBUG, "Radius: radius_Destroy\n"); 479 timer_Stop(&r->cx.timer); 480 route_DeleteAll(&r->routes); 481 free(r->filterid); 482 r->filterid = NULL; 483 free(r->msrepstr); 484 r->msrepstr = NULL; 485 free(r->repstr); 486 r->repstr = NULL; 487 free(r->errstr); 488 r->errstr = NULL; 489 if (r->cx.fd != -1) { 490 r->cx.fd = -1; 491 rad_close(r->cx.rad); 492 } 493 } 494 495 static int 496 radius_put_physical_details(struct rad_handle *rad, struct physical *p) 497 { 498 int slot, type; 499 500 type = RAD_VIRTUAL; 501 if (p->handler) 502 switch (p->handler->type) { 503 case I4B_DEVICE: 504 type = RAD_ISDN_SYNC; 505 break; 506 507 case TTY_DEVICE: 508 type = RAD_ASYNC; 509 break; 510 511 case ETHER_DEVICE: 512 type = RAD_ETHERNET; 513 break; 514 515 case TCP_DEVICE: 516 case UDP_DEVICE: 517 case EXEC_DEVICE: 518 case ATM_DEVICE: 519 case NG_DEVICE: 520 type = RAD_VIRTUAL; 521 break; 522 } 523 524 if (rad_put_int(rad, RAD_NAS_PORT_TYPE, type) != 0) { 525 log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad)); 526 rad_close(rad); 527 return 0; 528 } 529 530 if ((slot = physical_Slot(p)) >= 0) 531 if (rad_put_int(rad, RAD_NAS_PORT, slot) != 0) { 532 log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad)); 533 rad_close(rad); 534 return 0; 535 } 536 537 return 1; 538 } 539 540 /* 541 * Start an authentication request to the RADIUS server. 542 */ 543 int 544 radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, 545 const char *key, int klen, const char *nchallenge, 546 int nclen, const char *pchallenge, int pclen) 547 { 548 struct timeval tv; 549 int got; 550 char hostname[MAXHOSTNAMELEN]; 551 struct hostent *hp; 552 struct in_addr hostaddr; 553 #ifndef NODES 554 struct mschap_response msresp; 555 struct mschap2_response msresp2; 556 #endif 557 558 if (!*r->cfg.file) 559 return 0; 560 561 if (r->cx.fd != -1) 562 /* 563 * We assume that our name/key/challenge is the same as last time, 564 * and just continue to wait for the RADIUS server(s). 565 */ 566 return 1; 567 568 radius_Destroy(r); 569 570 if ((r->cx.rad = rad_auth_open()) == NULL) { 571 log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 572 return 0; 573 } 574 575 if (rad_config(r->cx.rad, r->cfg.file) != 0) { 576 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 577 rad_close(r->cx.rad); 578 return 0; 579 } 580 581 if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) { 582 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 583 rad_close(r->cx.rad); 584 return 0; 585 } 586 587 if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 || 588 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 589 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 590 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 591 rad_close(r->cx.rad); 592 return 0; 593 } 594 595 switch (authp->physical->link.lcp.want_auth) { 596 case PROTO_PAP: 597 /* We're talking PAP */ 598 if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) { 599 log_Printf(LogERROR, "PAP: rad_put_string: %s\n", 600 rad_strerror(r->cx.rad)); 601 rad_close(r->cx.rad); 602 return 0; 603 } 604 break; 605 606 case PROTO_CHAP: 607 switch (authp->physical->link.lcp.want_authtype) { 608 case 0x5: 609 if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 || 610 rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) { 611 log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", 612 rad_strerror(r->cx.rad)); 613 rad_close(r->cx.rad); 614 return 0; 615 } 616 break; 617 618 #ifndef NODES 619 case 0x80: 620 if (klen != 50) { 621 log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen); 622 rad_close(r->cx.rad); 623 return 0; 624 } 625 626 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 627 RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 628 msresp.ident = *key; 629 msresp.flags = 0x01; 630 memcpy(msresp.lm_response, key + 1, 24); 631 memcpy(msresp.nt_response, key + 25, 24); 632 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 633 RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp, 634 sizeof msresp); 635 break; 636 637 case 0x81: 638 if (klen != 50) { 639 log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen); 640 rad_close(r->cx.rad); 641 return 0; 642 } 643 644 if (pclen != sizeof msresp2.pchallenge) { 645 log_Printf(LogERROR, "CHAP81: Unrecognised peer challenge length %d\n", 646 pclen); 647 rad_close(r->cx.rad); 648 return 0; 649 } 650 651 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 652 RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 653 msresp2.ident = *key; 654 msresp2.flags = 0x00; 655 memcpy(msresp2.response, key + 25, 24); 656 memset(msresp2.reserved, '\0', sizeof msresp2.reserved); 657 memcpy(msresp2.pchallenge, pchallenge, pclen); 658 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 659 RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2, 660 sizeof msresp2); 661 break; 662 #endif 663 default: 664 log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n", 665 authp->physical->link.lcp.want_authtype); 666 rad_close(r->cx.rad); 667 return 0; 668 } 669 } 670 671 if (gethostname(hostname, sizeof hostname) != 0) 672 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 673 else { 674 if ((hp = gethostbyname(hostname)) != NULL) { 675 hostaddr.s_addr = *(u_long *)hp->h_addr; 676 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 677 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 678 rad_strerror(r->cx.rad)); 679 rad_close(r->cx.rad); 680 return 0; 681 } 682 } 683 if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 684 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 685 rad_strerror(r->cx.rad)); 686 rad_close(r->cx.rad); 687 return 0; 688 } 689 } 690 691 radius_put_physical_details(r->cx.rad, authp->physical); 692 693 r->cx.auth = authp; 694 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 695 radius_Process(r, got); 696 else { 697 log_Printf(LogPHASE, "Radius: Request sent\n"); 698 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 699 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 700 r->cx.timer.func = radius_Timeout; 701 r->cx.timer.name = "radius auth"; 702 r->cx.timer.arg = r; 703 timer_Start(&r->cx.timer); 704 } 705 706 return 1; 707 } 708 709 /* 710 * Send an accounting request to the RADIUS server 711 */ 712 void 713 radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl, 714 int acct_type, struct in_addr *peer_ip, struct in_addr *netmask, 715 struct pppThroughput *stats) 716 { 717 struct timeval tv; 718 int got; 719 char hostname[MAXHOSTNAMELEN]; 720 struct hostent *hp; 721 struct in_addr hostaddr; 722 723 if (!*r->cfg.file) 724 return; 725 726 if (r->cx.fd != -1) 727 /* 728 * We assume that our name/key/challenge is the same as last time, 729 * and just continue to wait for the RADIUS server(s). 730 */ 731 return; 732 733 radius_Destroy(r); 734 735 if ((r->cx.rad = rad_acct_open()) == NULL) { 736 log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 737 return; 738 } 739 740 if (rad_config(r->cx.rad, r->cfg.file) != 0) { 741 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 742 rad_close(r->cx.rad); 743 return; 744 } 745 746 if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) { 747 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 748 rad_close(r->cx.rad); 749 return; 750 } 751 752 /* Grab some accounting data and initialize structure */ 753 if (acct_type == RAD_START) { 754 ac->rad_parent = r; 755 /* Fetch username from datalink */ 756 strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name); 757 ac->user_name[AUTHLEN-1] = '\0'; 758 759 ac->authentic = 2; /* Assume RADIUS verified auth data */ 760 761 /* Generate a session ID */ 762 snprintf(ac->session_id, sizeof ac->session_id, "%s%d-%s%lu", 763 dl->bundle->cfg.auth.name, (int)getpid(), 764 dl->peer.authname, (unsigned long)stats->uptime); 765 766 /* And grab our MP socket name */ 767 snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s", 768 dl->bundle->ncp.mp.active ? 769 dl->bundle->ncp.mp.server.socket.sun_path : ""); 770 771 /* Fetch IP, netmask from IPCP */ 772 memcpy(&ac->ip, peer_ip, sizeof(ac->ip)); 773 memcpy(&ac->mask, netmask, sizeof(ac->mask)); 774 }; 775 776 if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 || 777 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 778 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0 || 779 rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS, ac->ip) != 0 || 780 rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK, ac->mask) != 0) { 781 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 782 rad_close(r->cx.rad); 783 return; 784 } 785 786 if (gethostname(hostname, sizeof hostname) != 0) 787 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 788 else { 789 if ((hp = gethostbyname(hostname)) != NULL) { 790 hostaddr.s_addr = *(u_long *)hp->h_addr; 791 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 792 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 793 rad_strerror(r->cx.rad)); 794 rad_close(r->cx.rad); 795 return; 796 } 797 } 798 if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 799 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 800 rad_strerror(r->cx.rad)); 801 rad_close(r->cx.rad); 802 return; 803 } 804 } 805 806 radius_put_physical_details(r->cx.rad, dl->physical); 807 808 if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 || 809 rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 || 810 rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID, 811 ac->multi_session_id) != 0 || 812 rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) { 813 /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */ 814 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 815 rad_close(r->cx.rad); 816 return; 817 } 818 819 if (acct_type == RAD_STOP) 820 /* Show some statistics */ 821 if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn) != 0 || 822 rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 || 823 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut) != 0 || 824 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut) 825 != 0 || 826 rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats)) 827 != 0) { 828 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 829 rad_close(r->cx.rad); 830 return; 831 } 832 833 r->cx.auth = NULL; /* Not valid for accounting requests */ 834 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 835 radius_Process(r, got); 836 else { 837 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 838 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 839 r->cx.timer.func = radius_Timeout; 840 r->cx.timer.name = "radius acct"; 841 r->cx.timer.arg = r; 842 timer_Start(&r->cx.timer); 843 } 844 } 845 846 /* 847 * How do things look at the moment ? 848 */ 849 void 850 radius_Show(struct radius *r, struct prompt *p) 851 { 852 prompt_Printf(p, " Radius config: %s", 853 *r->cfg.file ? r->cfg.file : "none"); 854 if (r->valid) { 855 prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip)); 856 prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask)); 857 prompt_Printf(p, " MTU: %lu\n", r->mtu); 858 prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis"); 859 prompt_Printf(p, " Message: %s\n", r->repstr ? r->repstr : ""); 860 prompt_Printf(p, " MS-CHAP2-Response: %s\n", 861 r->msrepstr ? r->msrepstr : ""); 862 prompt_Printf(p, " Error Message: %s\n", r->errstr ? r->errstr : ""); 863 if (r->routes) 864 route_ShowSticky(p, r->routes, " Routes", 16); 865 } else 866 prompt_Printf(p, " (not authenticated)\n"); 867 } 868