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