1/*********************************************************************** 2* 3* radius.c 4* 5* RADIUS plugin for pppd. Performs PAP, CHAP, MS-CHAP, MS-CHAPv2 6* authentication using RADIUS. 7* 8* Copyright (C) 2002 Roaring Penguin Software Inc. 9* 10* Based on a patch for ipppd, which is: 11* Copyright (C) 1996, Matjaz Godec <gody@elgo.si> 12* Copyright (C) 1996, Lars Fenneberg <in5y050@public.uni-hamburg.de> 13* Copyright (C) 1997, Miguel A.L. Paraz <map@iphil.net> 14* 15* Uses radiusclient library, which is: 16* Copyright (C) 1995,1996,1997,1998 Lars Fenneberg <lf@elemental.net> 17* Copyright (C) 2002 Roaring Penguin Software Inc. 18* 19* MPPE support is by Ralf Hofmann, <ralf.hofmann@elvido.net>, with 20* modification from Frank Cusack, <frank@google.com>. 21* 22* This plugin may be distributed according to the terms of the GNU 23* General Public License, version 2 or (at your option) any later version. 24* 25***********************************************************************/ 26static char const RCSID[] = 27"$Id: radius.c,v 1.28 2004/11/14 10:27:57 paulus Exp $"; 28 29#include "pppd.h" 30#include "chap-new.h" 31#ifdef CHAPMS 32#include "chap_ms.h" 33#ifdef MPPE 34#include "md5.h" 35#endif 36#endif 37#include "radiusclient.h" 38#include "fsm.h" 39#include "ipcp.h" 40#include <syslog.h> 41#include <sys/types.h> 42#include <sys/time.h> 43#include <string.h> 44#include <netinet/in.h> 45#include <stdlib.h> 46 47#define BUF_LEN 1024 48 49#define MD5_HASH_SIZE 16 50 51static char *config_file = NULL; 52static int add_avp(char **); 53static struct avpopt { 54 char *vpstr; 55 struct avpopt *next; 56} *avpopt = NULL; 57static bool portnummap = 0; 58 59static option_t Options[] = { 60 { "radius-config-file", o_string, &config_file }, 61 { "avpair", o_special, add_avp }, 62 { "map-to-ttyname", o_bool, &portnummap, 63 "Set Radius NAS-Port attribute value via libradiusclient library", OPT_PRIO | 1 }, 64 { "map-to-ifname", o_bool, &portnummap, 65 "Set Radius NAS-Port attribute to number as in interface name (Default)", OPT_PRIOSUB | 0 }, 66 { NULL } 67}; 68 69static int radius_secret_check(void); 70static int radius_pap_auth(char *user, 71 char *passwd, 72 char **msgp, 73 struct wordlist **paddrs, 74 struct wordlist **popts); 75static int radius_chap_verify(char *user, char *ourname, int id, 76 struct chap_digest_type *digest, 77 unsigned char *challenge, 78 unsigned char *response, 79 char *message, int message_space); 80 81static void radius_ip_up(void *opaque, int arg); 82static void radius_ip_down(void *opaque, int arg); 83static void make_username_realm(char *user); 84static int radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, 85 struct chap_digest_type *digest, 86 unsigned char *challenge, 87 char *message, int message_space); 88static void radius_choose_ip(u_int32_t *addrp); 89static int radius_init(char *msg); 90static int get_client_port(char *ifname); 91static int radius_allowed_address(u_int32_t addr); 92static void radius_acct_interim(void *); 93#ifdef MPPE 94static int radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, 95 unsigned char *); 96static int radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info); 97#endif 98 99#ifndef MAXSESSIONID 100#define MAXSESSIONID 32 101#endif 102 103#ifndef MAXCLASSLEN 104#define MAXCLASSLEN 500 105#endif 106 107struct radius_state { 108 int accounting_started; 109 int initialized; 110 int client_port; 111 int choose_ip; 112 int any_ip_addr_ok; 113 int done_chap_once; 114 u_int32_t ip_addr; 115 char user[MAXNAMELEN]; 116 char config_file[MAXPATHLEN]; 117 char session_id[MAXSESSIONID + 1]; 118 time_t start_time; 119 int acct_interim_interval; 120 SERVER *authserver; /* Authentication server to use */ 121 SERVER *acctserver; /* Accounting server to use */ 122 int class_len; 123 char class[MAXCLASSLEN]; 124 VALUE_PAIR *avp; /* Additional (user supplied) vp's to send to server */ 125}; 126 127void (*radius_attributes_hook)(VALUE_PAIR *) = NULL; 128 129/* The pre_auth_hook MAY set authserver and acctserver if it wants. 130 In that case, they override the values in the radiusclient.conf file */ 131void (*radius_pre_auth_hook)(char const *user, 132 SERVER **authserver, 133 SERVER **acctserver) = NULL; 134 135static struct radius_state rstate; 136 137char pppd_version[] = VERSION; 138 139/********************************************************************** 140* %FUNCTION: plugin_init 141* %ARGUMENTS: 142* None 143* %RETURNS: 144* Nothing 145* %DESCRIPTION: 146* Initializes RADIUS plugin. 147***********************************************************************/ 148void 149plugin_init(void) 150{ 151 pap_check_hook = radius_secret_check; 152 pap_auth_hook = radius_pap_auth; 153 154 chap_check_hook = radius_secret_check; 155 chap_verify_hook = radius_chap_verify; 156 157 ip_choose_hook = radius_choose_ip; 158 allowed_address_hook = radius_allowed_address; 159 160 add_notifier(&ip_up_notifier, radius_ip_up, NULL); 161 add_notifier(&ip_down_notifier, radius_ip_down, NULL); 162 163 memset(&rstate, 0, sizeof(rstate)); 164 165 strlcpy(rstate.config_file, "/etc/radiusclient/radiusclient.conf", 166 sizeof(rstate.config_file)); 167 168 add_options(Options); 169 170 info("RADIUS plugin initialized."); 171} 172 173/********************************************************************** 174* %FUNCTION: add_avp 175* %ARGUMENTS: 176* argv -- the <attribute=value> pair to add 177* %RETURNS: 178* 1 179* %DESCRIPTION: 180* Adds an av pair to be passed on to the RADIUS server on each request. 181***********************************************************************/ 182static int 183add_avp(char **argv) 184{ 185 struct avpopt *p = malloc(sizeof(struct avpopt)); 186 187 /* Append to a list of vp's for later parsing */ 188 p->vpstr = strdup(*argv); 189 p->next = avpopt; 190 avpopt = p; 191 192 return 1; 193} 194 195/********************************************************************** 196* %FUNCTION: radius_secret_check 197* %ARGUMENTS: 198* None 199* %RETURNS: 200* 1 -- we are ALWAYS willing to supply a secret. :-) 201* %DESCRIPTION: 202* Tells pppd that we will try to authenticate the peer, and not to 203* worry about looking in /etc/ppp/*-secrets 204***********************************************************************/ 205static int 206radius_secret_check(void) 207{ 208 return 1; 209} 210 211/********************************************************************** 212* %FUNCTION: radius_choose_ip 213* %ARGUMENTS: 214* addrp -- where to store the IP address 215* %RETURNS: 216* Nothing 217* %DESCRIPTION: 218* If RADIUS server has specified an IP address, it is stored in *addrp. 219***********************************************************************/ 220static void 221radius_choose_ip(u_int32_t *addrp) 222{ 223 if (rstate.choose_ip) { 224 *addrp = rstate.ip_addr; 225 } 226} 227 228/********************************************************************** 229* %FUNCTION: radius_pap_auth 230* %ARGUMENTS: 231* user -- user-name of peer 232* passwd -- password supplied by peer 233* msgp -- Message which will be sent in PAP response 234* paddrs -- set to a list of possible peer IP addresses 235* popts -- set to a list of additional pppd options 236* %RETURNS: 237* 1 if we can authenticate, -1 if we cannot. 238* %DESCRIPTION: 239* Performs PAP authentication using RADIUS 240***********************************************************************/ 241static int 242radius_pap_auth(char *user, 243 char *passwd, 244 char **msgp, 245 struct wordlist **paddrs, 246 struct wordlist **popts) 247{ 248 VALUE_PAIR *send, *received; 249 UINT4 av_type; 250 int result; 251 static char radius_msg[BUF_LEN]; 252 253 radius_msg[0] = 0; 254 *msgp = radius_msg; 255 256 if (radius_init(radius_msg) < 0) { 257 return 0; 258 } 259 260 /* Put user with potentially realm added in rstate.user */ 261 make_username_realm(user); 262 263 if (radius_pre_auth_hook) { 264 radius_pre_auth_hook(rstate.user, 265 &rstate.authserver, 266 &rstate.acctserver); 267 } 268 269 send = NULL; 270 received = NULL; 271 272 /* Hack... the "port" is the ppp interface number. Should really be 273 the tty */ 274 rstate.client_port = get_client_port(portnummap ? devnam : ifname); 275 276 av_type = PW_FRAMED; 277 rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE); 278 279 av_type = PW_PPP; 280 rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE); 281 282 rc_avpair_add(&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE); 283 rc_avpair_add(&send, PW_USER_PASSWORD, passwd, 0, VENDOR_NONE); 284 if (*remote_number) { 285 rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, 286 VENDOR_NONE); 287 } else if (ipparam) 288 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 289 290 /* Add user specified vp's */ 291 if (rstate.avp) 292 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 293 294 if (rstate.authserver) { 295 result = rc_auth_using_server(rstate.authserver, 296 rstate.client_port, send, 297 &received, radius_msg, NULL); 298 } else { 299 result = rc_auth(rstate.client_port, send, &received, radius_msg, NULL); 300 } 301 302 if (result == OK_RC) { 303 if (radius_setparams(received, radius_msg, NULL, NULL, NULL, NULL, 0) < 0) { 304 result = ERROR_RC; 305 } 306 } 307 308 /* free value pairs */ 309 rc_avpair_free(received); 310 rc_avpair_free(send); 311 312 return (result == OK_RC) ? 1 : 0; 313} 314 315/********************************************************************** 316* %FUNCTION: radius_chap_verify 317* %ARGUMENTS: 318* user -- name of the peer 319* ourname -- name for this machine 320* id -- the ID byte in the challenge 321* digest -- points to the structure representing the digest type 322* challenge -- the challenge string we sent (length in first byte) 323* response -- the response (hash) the peer sent back (length in 1st byte) 324* message -- space for a message to be returned to the peer 325* message_space -- number of bytes available at *message. 326* %RETURNS: 327* 1 if the response is good, 0 if it is bad 328* %DESCRIPTION: 329* Performs CHAP, MS-CHAP and MS-CHAPv2 authentication using RADIUS. 330***********************************************************************/ 331static int 332radius_chap_verify(char *user, char *ourname, int id, 333 struct chap_digest_type *digest, 334 unsigned char *challenge, unsigned char *response, 335 char *message, int message_space) 336{ 337 VALUE_PAIR *send, *received; 338 UINT4 av_type; 339 static char radius_msg[BUF_LEN]; 340 int result; 341 int challenge_len, response_len; 342 u_char cpassword[MAX_RESPONSE_LEN + 1]; 343#ifdef MPPE 344 /* Need the RADIUS secret and Request Authenticator to decode MPPE */ 345 REQUEST_INFO request_info, *req_info = &request_info; 346#else 347 REQUEST_INFO *req_info = NULL; 348#endif 349 350 challenge_len = *challenge++; 351 response_len = *response++; 352 353 radius_msg[0] = 0; 354 355 if (radius_init(radius_msg) < 0) { 356 error("%s", radius_msg); 357 return 0; 358 } 359 360 /* return error for types we can't handle */ 361 if ((digest->code != CHAP_MD5) 362#ifdef CHAPMS 363 && (digest->code != CHAP_MICROSOFT) 364 && (digest->code != CHAP_MICROSOFT_V2) 365#endif 366 ) { 367 error("RADIUS: Challenge type %u unsupported", digest->code); 368 return 0; 369 } 370 371 /* Put user with potentially realm added in rstate.user */ 372 if (!rstate.done_chap_once) { 373 make_username_realm(user); 374 rstate.client_port = get_client_port (portnummap ? devnam : ifname); 375 if (radius_pre_auth_hook) { 376 radius_pre_auth_hook(rstate.user, 377 &rstate.authserver, 378 &rstate.acctserver); 379 } 380 } 381 382 send = received = NULL; 383 384 av_type = PW_FRAMED; 385 rc_avpair_add (&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE); 386 387 av_type = PW_PPP; 388 rc_avpair_add (&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE); 389 390 rc_avpair_add (&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE); 391 392 /* 393 * add the challenge and response fields 394 */ 395 switch (digest->code) { 396 case CHAP_MD5: 397 /* CHAP-Challenge and CHAP-Password */ 398 if (response_len != MD5_HASH_SIZE) 399 return 0; 400 cpassword[0] = id; 401 memcpy(&cpassword[1], response, MD5_HASH_SIZE); 402 403 rc_avpair_add(&send, PW_CHAP_CHALLENGE, 404 challenge, challenge_len, VENDOR_NONE); 405 rc_avpair_add(&send, PW_CHAP_PASSWORD, 406 cpassword, MD5_HASH_SIZE + 1, VENDOR_NONE); 407 break; 408 409#ifdef CHAPMS 410 case CHAP_MICROSOFT: 411 { 412 /* MS-CHAP-Challenge and MS-CHAP-Response */ 413 MS_ChapResponse *rmd = (MS_ChapResponse *) response; 414 u_char *p = cpassword; 415 416 if (response_len != MS_CHAP_RESPONSE_LEN) 417 return 0; 418 *p++ = id; 419 /* The idiots use a different field order in RADIUS than PPP */ 420 memcpy(p, rmd->UseNT, sizeof(rmd->UseNT)); 421 p += sizeof(rmd->UseNT); 422 memcpy(p, rmd->LANManResp, sizeof(rmd->LANManResp)); 423 p += sizeof(rmd->LANManResp); 424 memcpy(p, rmd->NTResp, sizeof(rmd->NTResp)); 425 426 rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE, 427 challenge, challenge_len, VENDOR_MICROSOFT); 428 rc_avpair_add(&send, PW_MS_CHAP_RESPONSE, 429 cpassword, MS_CHAP_RESPONSE_LEN + 1, VENDOR_MICROSOFT); 430 break; 431 } 432 433 case CHAP_MICROSOFT_V2: 434 { 435 /* MS-CHAP-Challenge and MS-CHAP2-Response */ 436 MS_Chap2Response *rmd = (MS_Chap2Response *) response; 437 u_char *p = cpassword; 438 439 if (response_len != MS_CHAP2_RESPONSE_LEN) 440 return 0; 441 *p++ = id; 442 /* The idiots use a different field order in RADIUS than PPP */ 443 memcpy(p, rmd->Flags, sizeof(rmd->Flags)); 444 p += sizeof(rmd->Flags); 445 memcpy(p, rmd->PeerChallenge, sizeof(rmd->PeerChallenge)); 446 p += sizeof(rmd->PeerChallenge); 447 memcpy(p, rmd->Reserved, sizeof(rmd->Reserved)); 448 p += sizeof(rmd->Reserved); 449 memcpy(p, rmd->NTResp, sizeof(rmd->NTResp)); 450 451 rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE, 452 challenge, challenge_len, VENDOR_MICROSOFT); 453 rc_avpair_add(&send, PW_MS_CHAP2_RESPONSE, 454 cpassword, MS_CHAP2_RESPONSE_LEN + 1, VENDOR_MICROSOFT); 455 break; 456 } 457#endif 458 } 459 460 if (*remote_number) { 461 rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, 462 VENDOR_NONE); 463 } else if (ipparam) 464 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 465 466 /* Add user specified vp's */ 467 if (rstate.avp) 468 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 469 470 /* 471 * make authentication with RADIUS server 472 */ 473 474 if (rstate.authserver) { 475 result = rc_auth_using_server(rstate.authserver, 476 rstate.client_port, send, 477 &received, radius_msg, req_info); 478 } else { 479 result = rc_auth(rstate.client_port, send, &received, radius_msg, 480 req_info); 481 } 482 483 if (result == OK_RC) { 484 if (!rstate.done_chap_once) { 485 if (radius_setparams(received, radius_msg, req_info, digest, 486 challenge, message, message_space) < 0) { 487 error("%s", radius_msg); 488 result = ERROR_RC; 489 } else { 490 rstate.done_chap_once = 1; 491 } 492 } 493 } 494 495 rc_avpair_free(received); 496 rc_avpair_free (send); 497 return (result == OK_RC); 498} 499 500/********************************************************************** 501* %FUNCTION: make_username_realm 502* %ARGUMENTS: 503* user -- the user given to pppd 504* %RETURNS: 505* Nothing 506* %DESCRIPTION: 507* Copies user into rstate.user. If it lacks a realm (no "@domain" part), 508* then the default realm from the radiusclient config file is added. 509***********************************************************************/ 510static void 511make_username_realm(char *user) 512{ 513 char *default_realm; 514 515 if ( user != NULL ) { 516 strlcpy(rstate.user, user, sizeof(rstate.user)); 517 } else { 518 rstate.user[0] = 0; 519 } 520 521 default_realm = rc_conf_str("default_realm"); 522 523 if (!strchr(rstate.user, '@') && 524 default_realm && 525 (*default_realm != '\0')) { 526 strlcat(rstate.user, "@", sizeof(rstate.user)); 527 strlcat(rstate.user, default_realm, sizeof(rstate.user)); 528 } 529} 530 531/********************************************************************** 532* %FUNCTION: radius_setparams 533* %ARGUMENTS: 534* vp -- received value-pairs 535* msg -- buffer in which to place error message. Holds up to BUF_LEN chars 536* %RETURNS: 537* >= 0 on success; -1 on failure 538* %DESCRIPTION: 539* Parses attributes sent by RADIUS server and sets them in pppd. 540***********************************************************************/ 541static int 542radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, 543 struct chap_digest_type *digest, unsigned char *challenge, 544 char *message, int message_space) 545{ 546 u_int32_t remote; 547 int ms_chap2_success = 0; 548#ifdef MPPE 549 int mppe_enc_keys = 0; /* whether or not these were received */ 550 int mppe_enc_policy = 0; 551 int mppe_enc_types = 0; 552#endif 553 554 /* Send RADIUS attributes to anyone else who might be interested */ 555 if (radius_attributes_hook) { 556 (*radius_attributes_hook)(vp); 557 } 558 559 /* 560 * service type (if not framed then quit), 561 * new IP address (RADIUS can define static IP for some users), 562 */ 563 564 while (vp) { 565 if (vp->vendorcode == VENDOR_NONE) { 566 switch (vp->attribute) { 567 case PW_SERVICE_TYPE: 568 /* check for service type */ 569 /* if not FRAMED then exit */ 570 if (vp->lvalue != PW_FRAMED) { 571 slprintf(msg, BUF_LEN, "RADIUS: wrong service type %ld for %s", 572 vp->lvalue, rstate.user); 573 return -1; 574 } 575 break; 576 577 case PW_FRAMED_PROTOCOL: 578 /* check for framed protocol type */ 579 /* if not PPP then also exit */ 580 if (vp->lvalue != PW_PPP) { 581 slprintf(msg, BUF_LEN, "RADIUS: wrong framed protocol %ld for %s", 582 vp->lvalue, rstate.user); 583 return -1; 584 } 585 break; 586 587 case PW_SESSION_TIMEOUT: 588 /* Session timeout */ 589 maxconnect = vp->lvalue; 590 break; 591#ifdef MAXOCTETS 592 case PW_SESSION_OCTETS_LIMIT: 593 /* Session traffic limit */ 594 maxoctets = vp->lvalue; 595 break; 596 case PW_OCTETS_DIRECTION: 597 /* Session traffic limit direction check */ 598 maxoctets_dir = ( vp->lvalue > 4 ) ? 0 : vp->lvalue ; 599 break; 600#endif 601 case PW_ACCT_INTERIM_INTERVAL: 602 /* Send accounting updates every few seconds */ 603 rstate.acct_interim_interval = vp->lvalue; 604 /* RFC says it MUST NOT be less than 60 seconds */ 605 /* We use "0" to signify not sending updates */ 606 if (rstate.acct_interim_interval && 607 rstate.acct_interim_interval < 60) { 608 rstate.acct_interim_interval = 60; 609 } 610 break; 611 case PW_FRAMED_IP_ADDRESS: 612 /* seting up remote IP addresses */ 613 remote = vp->lvalue; 614 if (remote == 0xffffffff) { 615 /* 0xffffffff means user should be allowed to select one */ 616 rstate.any_ip_addr_ok = 1; 617 } else if (remote != 0xfffffffe) { 618 /* 0xfffffffe means NAS should select an ip address */ 619 remote = htonl(vp->lvalue); 620 if (bad_ip_adrs (remote)) { 621 slprintf(msg, BUF_LEN, "RADIUS: bad remote IP address %I for %s", 622 remote, rstate.user); 623 return -1; 624 } 625 rstate.choose_ip = 1; 626 rstate.ip_addr = remote; 627 } 628 break; 629 case PW_CLASS: 630 /* Save Class attribute to pass it in accounting request */ 631 if (vp->lvalue <= MAXCLASSLEN) { 632 rstate.class_len=vp->lvalue; 633 memcpy(rstate.class, vp->strvalue, rstate.class_len); 634 } /* else too big for our buffer - ignore it */ 635 break; 636 } 637 638 639#ifdef CHAPMS 640 } else if (vp->vendorcode == VENDOR_MICROSOFT) { 641 switch (vp->attribute) { 642 case PW_MS_CHAP2_SUCCESS: 643 if ((vp->lvalue != 43) || strncmp(vp->strvalue + 1, "S=", 2)) { 644 slprintf(msg,BUF_LEN,"RADIUS: bad MS-CHAP2-Success packet"); 645 return -1; 646 } 647 if (message != NULL) 648 strlcpy(message, vp->strvalue + 1, message_space); 649 ms_chap2_success = 1; 650 break; 651 652#ifdef MPPE 653 case PW_MS_CHAP_MPPE_KEYS: 654 if (radius_setmppekeys(vp, req_info, challenge) < 0) { 655 slprintf(msg, BUF_LEN, 656 "RADIUS: bad MS-CHAP-MPPE-Keys attribute"); 657 return -1; 658 } 659 mppe_enc_keys = 1; 660 break; 661 662 case PW_MS_MPPE_SEND_KEY: 663 case PW_MS_MPPE_RECV_KEY: 664 if (radius_setmppekeys2(vp, req_info) < 0) { 665 slprintf(msg, BUF_LEN, 666 "RADIUS: bad MS-MPPE-%s-Key attribute", 667 (vp->attribute == PW_MS_MPPE_SEND_KEY)? 668 "Send": "Recv"); 669 return -1; 670 } 671 mppe_enc_keys = 1; 672 break; 673 674 case PW_MS_MPPE_ENCRYPTION_POLICY: 675 mppe_enc_policy = vp->lvalue; /* save for later */ 676 break; 677 678 case PW_MS_MPPE_ENCRYPTION_TYPES: 679 mppe_enc_types = vp->lvalue; /* save for later */ 680 break; 681 682#endif /* MPPE */ 683#if 0 684 case PW_MS_PRIMARY_DNS_SERVER: 685 case PW_MS_SECONDARY_DNS_SERVER: 686 case PW_MS_PRIMARY_NBNS_SERVER: 687 case PW_MS_SECONDARY_NBNS_SERVER: 688 break; 689#endif 690 } 691#endif /* CHAPMS */ 692 } 693 vp = vp->next; 694 } 695 696 /* Require a valid MS-CHAP2-SUCCESS for MS-CHAPv2 auth */ 697 if (digest && (digest->code == CHAP_MICROSOFT_V2) && !ms_chap2_success) 698 return -1; 699 700#ifdef MPPE 701 /* 702 * Require both policy and key attributes to indicate a valid key. 703 * Note that if the policy value was '0' we don't set the key! 704 */ 705 if (mppe_enc_policy && mppe_enc_keys) { 706 mppe_keys_set = 1; 707 /* Set/modify allowed encryption types. */ 708 if (mppe_enc_types) 709 set_mppe_enc_types(mppe_enc_policy, mppe_enc_types); 710 } 711#endif 712 713 return 0; 714} 715 716#ifdef MPPE 717/********************************************************************** 718* %FUNCTION: radius_setmppekeys 719* %ARGUMENTS: 720* vp -- value pair holding MS-CHAP-MPPE-KEYS attribute 721* req_info -- radius request information used for encryption 722* %RETURNS: 723* >= 0 on success; -1 on failure 724* %DESCRIPTION: 725* Decrypt the "key" provided by the RADIUS server for MPPE encryption. 726* See RFC 2548. 727***********************************************************************/ 728static int 729radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, 730 unsigned char *challenge) 731{ 732 int i; 733 MD5_CTX Context; 734 u_char plain[32]; 735 u_char buf[16]; 736 737 if (vp->lvalue != 32) { 738 error("RADIUS: Incorrect attribute length (%d) for MS-CHAP-MPPE-Keys", 739 vp->lvalue); 740 return -1; 741 } 742 743 memcpy(plain, vp->strvalue, sizeof(plain)); 744 745 MD5_Init(&Context); 746 MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); 747 MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); 748 MD5_Final(buf, &Context); 749 750 for (i = 0; i < 16; i++) 751 plain[i] ^= buf[i]; 752 753 MD5_Init(&Context); 754 MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); 755 MD5_Update(&Context, vp->strvalue, 16); 756 MD5_Final(buf, &Context); 757 758 for(i = 0; i < 16; i++) 759 plain[i + 16] ^= buf[i]; 760 761 /* 762 * Annoying. The "key" returned is just the NTPasswordHashHash, which 763 * the NAS (us) doesn't need; we only need the start key. So we have 764 * to generate the start key, sigh. NB: We do not support the LM-Key. 765 */ 766 mppe_set_keys(challenge, &plain[8]); 767 768 return 0; 769} 770 771/********************************************************************** 772* %FUNCTION: radius_setmppekeys2 773* %ARGUMENTS: 774* vp -- value pair holding MS-MPPE-SEND-KEY or MS-MPPE-RECV-KEY attribute 775* req_info -- radius request information used for encryption 776* %RETURNS: 777* >= 0 on success; -1 on failure 778* %DESCRIPTION: 779* Decrypt the key provided by the RADIUS server for MPPE encryption. 780* See RFC 2548. 781***********************************************************************/ 782static int 783radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info) 784{ 785 int i; 786 MD5_CTX Context; 787 u_char *salt = vp->strvalue; 788 u_char *crypt = vp->strvalue + 2; 789 u_char plain[32]; 790 u_char buf[MD5_HASH_SIZE]; 791 char *type = "Send"; 792 793 if (vp->attribute == PW_MS_MPPE_RECV_KEY) 794 type = "Recv"; 795 796 if (vp->lvalue != 34) { 797 error("RADIUS: Incorrect attribute length (%d) for MS-MPPE-%s-Key", 798 vp->lvalue, type); 799 return -1; 800 } 801 802 if ((salt[0] & 0x80) == 0) { 803 error("RADIUS: Illegal salt value for MS-MPPE-%s-Key attribute", type); 804 return -1; 805 } 806 807 memcpy(plain, crypt, 32); 808 809 MD5_Init(&Context); 810 MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); 811 MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); 812 MD5_Update(&Context, salt, 2); 813 MD5_Final(buf, &Context); 814 815 for (i = 0; i < 16; i++) 816 plain[i] ^= buf[i]; 817 818 if (plain[0] != sizeof(mppe_send_key) /* 16 */) { 819 error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute", 820 (int) plain[0], type); 821 return -1; 822 } 823 824 MD5_Init(&Context); 825 MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); 826 MD5_Update(&Context, crypt, 16); 827 MD5_Final(buf, &Context); 828 829 plain[16] ^= buf[0]; /* only need the first byte */ 830 831 if (vp->attribute == PW_MS_MPPE_SEND_KEY) 832 memcpy(mppe_send_key, plain + 1, 16); 833 else 834 memcpy(mppe_recv_key, plain + 1, 16); 835 836 return 0; 837} 838#endif /* MPPE */ 839 840/********************************************************************** 841* %FUNCTION: radius_acct_start 842* %ARGUMENTS: 843* None 844* %RETURNS: 845* Nothing 846* %DESCRIPTION: 847* Sends a "start" accounting message to the RADIUS server. 848***********************************************************************/ 849static void 850radius_acct_start(void) 851{ 852 UINT4 av_type; 853 int result; 854 VALUE_PAIR *send = NULL; 855 ipcp_options *ho = &ipcp_hisoptions[0]; 856 u_int32_t hisaddr; 857 858 if (!rstate.initialized) { 859 return; 860 } 861 862 rstate.start_time = time(NULL); 863 864 strncpy(rstate.session_id, rc_mksid(), sizeof(rstate.session_id)); 865 866 rc_avpair_add(&send, PW_ACCT_SESSION_ID, 867 rstate.session_id, 0, VENDOR_NONE); 868 rc_avpair_add(&send, PW_USER_NAME, 869 rstate.user, 0, VENDOR_NONE); 870 871 if (rstate.class_len > 0) 872 rc_avpair_add(&send, PW_CLASS, 873 rstate.class, rstate.class_len, VENDOR_NONE); 874 875 av_type = PW_STATUS_START; 876 rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); 877 878 av_type = PW_FRAMED; 879 rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE); 880 881 av_type = PW_PPP; 882 rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE); 883 884 if (*remote_number) { 885 rc_avpair_add(&send, PW_CALLING_STATION_ID, 886 remote_number, 0, VENDOR_NONE); 887 } else if (ipparam) 888 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 889 890 av_type = PW_RADIUS; 891 rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE); 892 893 894 av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) ); 895 rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE); 896 897 hisaddr = ho->hisaddr; 898 av_type = htonl(hisaddr); 899 rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); 900 901 /* Add user specified vp's */ 902 if (rstate.avp) 903 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 904 905 if (rstate.acctserver) { 906 result = rc_acct_using_server(rstate.acctserver, 907 rstate.client_port, send); 908 } else { 909 result = rc_acct(rstate.client_port, send); 910 } 911 912 rc_avpair_free(send); 913 914 if (result != OK_RC) { 915 /* RADIUS server could be down so make this a warning */ 916 syslog(LOG_WARNING, 917 "Accounting START failed for %s", rstate.user); 918 } else { 919 rstate.accounting_started = 1; 920 /* Kick off periodic accounting reports */ 921 if (rstate.acct_interim_interval) { 922 TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); 923 } 924 } 925} 926 927/********************************************************************** 928* %FUNCTION: radius_acct_stop 929* %ARGUMENTS: 930* None 931* %RETURNS: 932* Nothing 933* %DESCRIPTION: 934* Sends a "stop" accounting message to the RADIUS server. 935***********************************************************************/ 936static void 937radius_acct_stop(void) 938{ 939 UINT4 av_type; 940 VALUE_PAIR *send = NULL; 941 ipcp_options *ho = &ipcp_hisoptions[0]; 942 u_int32_t hisaddr; 943 int result; 944 945 if (!rstate.initialized) { 946 return; 947 } 948 949 if (!rstate.accounting_started) { 950 return; 951 } 952 953 rstate.accounting_started = 0; 954 rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 955 0, VENDOR_NONE); 956 957 rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE); 958 959 av_type = PW_STATUS_STOP; 960 rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); 961 962 av_type = PW_FRAMED; 963 rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE); 964 965 av_type = PW_PPP; 966 rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE); 967 968 av_type = PW_RADIUS; 969 rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE); 970 971 972 if (link_stats_valid) { 973 av_type = link_connect_time; 974 rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE); 975 976 av_type = link_stats.bytes_out; 977 rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE); 978 979 av_type = link_stats.bytes_in; 980 rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE); 981 982 av_type = link_stats.pkts_out; 983 rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE); 984 985 av_type = link_stats.pkts_in; 986 rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE); 987 } 988 989 if (*remote_number) { 990 rc_avpair_add(&send, PW_CALLING_STATION_ID, 991 remote_number, 0, VENDOR_NONE); 992 } else if (ipparam) 993 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 994 995 av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) ); 996 rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE); 997 998 av_type = PW_NAS_ERROR; 999 switch( status ) { 1000 case EXIT_OK: 1001 case EXIT_USER_REQUEST: 1002 av_type = PW_USER_REQUEST; 1003 break; 1004 1005 case EXIT_HANGUP: 1006 case EXIT_PEER_DEAD: 1007 case EXIT_CONNECT_FAILED: 1008 av_type = PW_LOST_CARRIER; 1009 break; 1010 1011 case EXIT_INIT_FAILED: 1012 case EXIT_OPEN_FAILED: 1013 case EXIT_LOCK_FAILED: 1014 case EXIT_PTYCMD_FAILED: 1015 av_type = PW_PORT_ERROR; 1016 break; 1017 1018 case EXIT_PEER_AUTH_FAILED: 1019 case EXIT_AUTH_TOPEER_FAILED: 1020 case EXIT_NEGOTIATION_FAILED: 1021 case EXIT_CNID_AUTH_FAILED: 1022 av_type = PW_SERVICE_UNAVAILABLE; 1023 break; 1024 1025 case EXIT_IDLE_TIMEOUT: 1026 av_type = PW_ACCT_IDLE_TIMEOUT; 1027 break; 1028 1029 case EXIT_CONNECT_TIME: 1030 av_type = PW_ACCT_SESSION_TIMEOUT; 1031 break; 1032 1033#ifdef MAXOCTETS 1034 case EXIT_TRAFFIC_LIMIT: 1035 av_type = PW_NAS_REQUEST; 1036 break; 1037#endif 1038 1039 default: 1040 av_type = PW_NAS_ERROR; 1041 break; 1042 } 1043 rc_avpair_add(&send, PW_ACCT_TERMINATE_CAUSE, &av_type, 0, VENDOR_NONE); 1044 1045 hisaddr = ho->hisaddr; 1046 av_type = htonl(hisaddr); 1047 rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); 1048 1049 /* Add user specified vp's */ 1050 if (rstate.avp) 1051 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 1052 1053 if (rstate.acctserver) { 1054 result = rc_acct_using_server(rstate.acctserver, 1055 rstate.client_port, send); 1056 } else { 1057 result = rc_acct(rstate.client_port, send); 1058 } 1059 1060 if (result != OK_RC) { 1061 /* RADIUS server could be down so make this a warning */ 1062 syslog(LOG_WARNING, 1063 "Accounting STOP failed for %s", rstate.user); 1064 } 1065 rc_avpair_free(send); 1066} 1067 1068/********************************************************************** 1069* %FUNCTION: radius_acct_interim 1070* %ARGUMENTS: 1071* None 1072* %RETURNS: 1073* Nothing 1074* %DESCRIPTION: 1075* Sends an interim accounting message to the RADIUS server 1076***********************************************************************/ 1077static void 1078radius_acct_interim(void *ignored) 1079{ 1080 UINT4 av_type; 1081 VALUE_PAIR *send = NULL; 1082 ipcp_options *ho = &ipcp_hisoptions[0]; 1083 u_int32_t hisaddr; 1084 int result; 1085 1086 if (!rstate.initialized) { 1087 return; 1088 } 1089 1090 if (!rstate.accounting_started) { 1091 return; 1092 } 1093 1094 rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 1095 0, VENDOR_NONE); 1096 1097 rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE); 1098 1099 av_type = PW_STATUS_ALIVE; 1100 rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); 1101 1102 av_type = PW_FRAMED; 1103 rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE); 1104 1105 av_type = PW_PPP; 1106 rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE); 1107 1108 av_type = PW_RADIUS; 1109 rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE); 1110 1111 /* Update link stats */ 1112 update_link_stats(0); 1113 1114 if (link_stats_valid) { 1115 link_stats_valid = 0; /* Force later code to update */ 1116 1117 av_type = link_connect_time; 1118 rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE); 1119 1120 av_type = link_stats.bytes_out; 1121 rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE); 1122 1123 av_type = link_stats.bytes_in; 1124 rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE); 1125 1126 av_type = link_stats.pkts_out; 1127 rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE); 1128 1129 av_type = link_stats.pkts_in; 1130 rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE); 1131 } 1132 1133 if (*remote_number) { 1134 rc_avpair_add(&send, PW_CALLING_STATION_ID, 1135 remote_number, 0, VENDOR_NONE); 1136 } else if (ipparam) 1137 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 1138 1139 av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) ); 1140 rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE); 1141 1142 hisaddr = ho->hisaddr; 1143 av_type = htonl(hisaddr); 1144 rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); 1145 1146 /* Add user specified vp's */ 1147 if (rstate.avp) 1148 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 1149 1150 if (rstate.acctserver) { 1151 result = rc_acct_using_server(rstate.acctserver, 1152 rstate.client_port, send); 1153 } else { 1154 result = rc_acct(rstate.client_port, send); 1155 } 1156 1157 if (result != OK_RC) { 1158 /* RADIUS server could be down so make this a warning */ 1159 syslog(LOG_WARNING, 1160 "Interim accounting failed for %s", rstate.user); 1161 } 1162 rc_avpair_free(send); 1163 1164 /* Schedule another one */ 1165 TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); 1166} 1167 1168/********************************************************************** 1169* %FUNCTION: radius_ip_up 1170* %ARGUMENTS: 1171* opaque -- ignored 1172* arg -- ignored 1173* %RETURNS: 1174* Nothing 1175* %DESCRIPTION: 1176* Called when IPCP is up. We'll do a start-accounting record. 1177***********************************************************************/ 1178static void 1179radius_ip_up(void *opaque, int arg) 1180{ 1181 radius_acct_start(); 1182} 1183 1184/********************************************************************** 1185* %FUNCTION: radius_ip_down 1186* %ARGUMENTS: 1187* opaque -- ignored 1188* arg -- ignored 1189* %RETURNS: 1190* Nothing 1191* %DESCRIPTION: 1192* Called when IPCP is down. We'll do a stop-accounting record. 1193***********************************************************************/ 1194static void 1195radius_ip_down(void *opaque, int arg) 1196{ 1197 radius_acct_stop(); 1198} 1199 1200/********************************************************************** 1201* %FUNCTION: radius_init 1202* %ARGUMENTS: 1203* msg -- buffer of size BUF_LEN for error message 1204* %RETURNS: 1205* negative on failure; non-negative on success 1206* %DESCRIPTION: 1207* Initializes radiusclient library 1208***********************************************************************/ 1209static int 1210radius_init(char *msg) 1211{ 1212 if (rstate.initialized) { 1213 return 0; 1214 } 1215 1216 if (config_file && *config_file) { 1217 strlcpy(rstate.config_file, config_file, MAXPATHLEN-1); 1218 } 1219 1220 rstate.initialized = 1; 1221 1222 if (rc_read_config(rstate.config_file) != 0) { 1223 slprintf(msg, BUF_LEN, "RADIUS: Can't read config file %s", 1224 rstate.config_file); 1225 return -1; 1226 } 1227 1228 if (rc_read_dictionary(rc_conf_str("dictionary")) != 0) { 1229 slprintf(msg, BUF_LEN, "RADIUS: Can't read dictionary file %s", 1230 rc_conf_str("dictionary")); 1231 return -1; 1232 } 1233 1234 if (rc_read_mapfile(rc_conf_str("mapfile")) != 0) { 1235 slprintf(msg, BUF_LEN, "RADIUS: Can't read map file %s", 1236 rc_conf_str("mapfile")); 1237 return -1; 1238 } 1239 1240 /* Add av pairs saved during option parsing */ 1241 while (avpopt) { 1242 struct avpopt *n = avpopt->next; 1243 1244 rc_avpair_parse(avpopt->vpstr, &rstate.avp); 1245 free(avpopt->vpstr); 1246 free(avpopt); 1247 avpopt = n; 1248 } 1249 return 0; 1250} 1251 1252/********************************************************************** 1253* %FUNCTION: get_client_port 1254* %ARGUMENTS: 1255* ifname -- PPP interface name (e.g. "ppp7") 1256* %RETURNS: 1257* The NAS port number (e.g. 7) 1258* %DESCRIPTION: 1259* Extracts the port number from the interface name 1260***********************************************************************/ 1261static int 1262get_client_port(char *ifname) 1263{ 1264 int port; 1265 if (sscanf(ifname, "ppp%d", &port) == 1) { 1266 return port; 1267 } 1268 return rc_map2id(ifname); 1269} 1270 1271/********************************************************************** 1272* %FUNCTION: radius_allowed_address 1273* %ARGUMENTS: 1274* addr -- IP address 1275* %RETURNS: 1276* 1 if we're allowed to use that IP address; 0 if not; -1 if we do 1277* not know. 1278***********************************************************************/ 1279static int 1280radius_allowed_address(u_int32_t addr) 1281{ 1282 ipcp_options *wo = &ipcp_wantoptions[0]; 1283 1284 if (!rstate.choose_ip) { 1285 /* If RADIUS server said any address is OK, then fine... */ 1286 if (rstate.any_ip_addr_ok) { 1287 return 1; 1288 } 1289 1290 /* Sigh... if an address was supplied for remote host in pppd 1291 options, it has to match that. */ 1292 if (wo->hisaddr != 0 && wo->hisaddr == addr) { 1293 return 1; 1294 } 1295 1296 return 0; 1297 } 1298 if (addr == rstate.ip_addr) return 1; 1299 return 0; 1300} 1301 1302/* Useful for other plugins */ 1303char *radius_logged_in_user(void) 1304{ 1305 return rstate.user; 1306} 1307