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.31 2006/05/22 00:01:40 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 u_char *p = cpassword; 414 415 if (response_len != MS_CHAP_RESPONSE_LEN) 416 return 0; 417 *p++ = id; 418 /* The idiots use a different field order in RADIUS than PPP */ 419 *p++ = response[MS_CHAP_USENT]; 420 memcpy(p, response, MS_CHAP_LANMANRESP_LEN + MS_CHAP_NTRESP_LEN); 421 422 rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE, 423 challenge, challenge_len, VENDOR_MICROSOFT); 424 rc_avpair_add(&send, PW_MS_CHAP_RESPONSE, 425 cpassword, MS_CHAP_RESPONSE_LEN + 1, VENDOR_MICROSOFT); 426 break; 427 } 428 429 case CHAP_MICROSOFT_V2: 430 { 431 /* MS-CHAP-Challenge and MS-CHAP2-Response */ 432 u_char *p = cpassword; 433 434 if (response_len != MS_CHAP2_RESPONSE_LEN) 435 return 0; 436 *p++ = id; 437 /* The idiots use a different field order in RADIUS than PPP */ 438 *p++ = response[MS_CHAP2_FLAGS]; 439 memcpy(p, response, (MS_CHAP2_PEER_CHAL_LEN + MS_CHAP2_RESERVED_LEN 440 + MS_CHAP2_NTRESP_LEN)); 441 442 rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE, 443 challenge, challenge_len, VENDOR_MICROSOFT); 444 rc_avpair_add(&send, PW_MS_CHAP2_RESPONSE, 445 cpassword, MS_CHAP2_RESPONSE_LEN + 1, VENDOR_MICROSOFT); 446 break; 447 } 448#endif 449 } 450 451 if (*remote_number) { 452 rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, 453 VENDOR_NONE); 454 } else if (ipparam) 455 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 456 457 /* Add user specified vp's */ 458 if (rstate.avp) 459 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 460 461 /* 462 * make authentication with RADIUS server 463 */ 464 465 if (rstate.authserver) { 466 result = rc_auth_using_server(rstate.authserver, 467 rstate.client_port, send, 468 &received, radius_msg, req_info); 469 } else { 470 result = rc_auth(rstate.client_port, send, &received, radius_msg, 471 req_info); 472 } 473 474 strlcpy(message, radius_msg, message_space); 475 476 if (result == OK_RC) { 477 if (!rstate.done_chap_once) { 478 if (radius_setparams(received, radius_msg, req_info, digest, 479 challenge, message, message_space) < 0) { 480 error("%s", radius_msg); 481 result = ERROR_RC; 482 } else { 483 rstate.done_chap_once = 1; 484 } 485 } 486 } 487 488 rc_avpair_free(received); 489 rc_avpair_free (send); 490 return (result == OK_RC); 491} 492 493/********************************************************************** 494* %FUNCTION: make_username_realm 495* %ARGUMENTS: 496* user -- the user given to pppd 497* %RETURNS: 498* Nothing 499* %DESCRIPTION: 500* Copies user into rstate.user. If it lacks a realm (no "@domain" part), 501* then the default realm from the radiusclient config file is added. 502***********************************************************************/ 503static void 504make_username_realm(char *user) 505{ 506 char *default_realm; 507 508 if ( user != NULL ) { 509 strlcpy(rstate.user, user, sizeof(rstate.user)); 510 } else { 511 rstate.user[0] = 0; 512 } 513 514 default_realm = rc_conf_str("default_realm"); 515 516 if (!strchr(rstate.user, '@') && 517 default_realm && 518 (*default_realm != '\0')) { 519 strlcat(rstate.user, "@", sizeof(rstate.user)); 520 strlcat(rstate.user, default_realm, sizeof(rstate.user)); 521 } 522} 523 524/********************************************************************** 525* %FUNCTION: radius_setparams 526* %ARGUMENTS: 527* vp -- received value-pairs 528* msg -- buffer in which to place error message. Holds up to BUF_LEN chars 529* %RETURNS: 530* >= 0 on success; -1 on failure 531* %DESCRIPTION: 532* Parses attributes sent by RADIUS server and sets them in pppd. 533***********************************************************************/ 534static int 535radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, 536 struct chap_digest_type *digest, unsigned char *challenge, 537 char *message, int message_space) 538{ 539 u_int32_t remote; 540 int ms_chap2_success = 0; 541#ifdef MPPE 542 int mppe_enc_keys = 0; /* whether or not these were received */ 543 int mppe_enc_policy = 0; 544 int mppe_enc_types = 0; 545#endif 546 547 /* Send RADIUS attributes to anyone else who might be interested */ 548 if (radius_attributes_hook) { 549 (*radius_attributes_hook)(vp); 550 } 551 552 /* 553 * service type (if not framed then quit), 554 * new IP address (RADIUS can define static IP for some users), 555 */ 556 557 while (vp) { 558 if (vp->vendorcode == VENDOR_NONE) { 559 switch (vp->attribute) { 560 case PW_SERVICE_TYPE: 561 /* check for service type */ 562 /* if not FRAMED then exit */ 563 if (vp->lvalue != PW_FRAMED) { 564 slprintf(msg, BUF_LEN, "RADIUS: wrong service type %ld for %s", 565 vp->lvalue, rstate.user); 566 return -1; 567 } 568 break; 569 570 case PW_FRAMED_PROTOCOL: 571 /* check for framed protocol type */ 572 /* if not PPP then also exit */ 573 if (vp->lvalue != PW_PPP) { 574 slprintf(msg, BUF_LEN, "RADIUS: wrong framed protocol %ld for %s", 575 vp->lvalue, rstate.user); 576 return -1; 577 } 578 break; 579 580 case PW_SESSION_TIMEOUT: 581 /* Session timeout */ 582 maxconnect = vp->lvalue; 583 break; 584#ifdef MAXOCTETS 585 case PW_SESSION_OCTETS_LIMIT: 586 /* Session traffic limit */ 587 maxoctets = vp->lvalue; 588 break; 589 case PW_OCTETS_DIRECTION: 590 /* Session traffic limit direction check */ 591 maxoctets_dir = ( vp->lvalue > 4 ) ? 0 : vp->lvalue ; 592 break; 593#endif 594 case PW_ACCT_INTERIM_INTERVAL: 595 /* Send accounting updates every few seconds */ 596 rstate.acct_interim_interval = vp->lvalue; 597 /* RFC says it MUST NOT be less than 60 seconds */ 598 /* We use "0" to signify not sending updates */ 599 if (rstate.acct_interim_interval && 600 rstate.acct_interim_interval < 60) { 601 rstate.acct_interim_interval = 60; 602 } 603 break; 604 case PW_FRAMED_IP_ADDRESS: 605 /* seting up remote IP addresses */ 606 remote = vp->lvalue; 607 if (remote == 0xffffffff) { 608 /* 0xffffffff means user should be allowed to select one */ 609 rstate.any_ip_addr_ok = 1; 610 } else if (remote != 0xfffffffe) { 611 /* 0xfffffffe means NAS should select an ip address */ 612 remote = htonl(vp->lvalue); 613 if (bad_ip_adrs (remote)) { 614 slprintf(msg, BUF_LEN, "RADIUS: bad remote IP address %I for %s", 615 remote, rstate.user); 616 return -1; 617 } 618 rstate.choose_ip = 1; 619 rstate.ip_addr = remote; 620 } 621 break; 622 case PW_CLASS: 623 /* Save Class attribute to pass it in accounting request */ 624 if (vp->lvalue <= MAXCLASSLEN) { 625 rstate.class_len=vp->lvalue; 626 memcpy(rstate.class, vp->strvalue, rstate.class_len); 627 } /* else too big for our buffer - ignore it */ 628 break; 629 } 630 631 632#ifdef CHAPMS 633 } else if (vp->vendorcode == VENDOR_MICROSOFT) { 634 switch (vp->attribute) { 635 case PW_MS_CHAP2_SUCCESS: 636 if ((vp->lvalue != 43) || strncmp(vp->strvalue + 1, "S=", 2)) { 637 slprintf(msg,BUF_LEN,"RADIUS: bad MS-CHAP2-Success packet"); 638 return -1; 639 } 640 if (message != NULL) 641 strlcpy(message, vp->strvalue + 1, message_space); 642 ms_chap2_success = 1; 643 break; 644 645#ifdef MPPE 646 case PW_MS_CHAP_MPPE_KEYS: 647 if (radius_setmppekeys(vp, req_info, challenge) < 0) { 648 slprintf(msg, BUF_LEN, 649 "RADIUS: bad MS-CHAP-MPPE-Keys attribute"); 650 return -1; 651 } 652 mppe_enc_keys = 1; 653 break; 654 655 case PW_MS_MPPE_SEND_KEY: 656 case PW_MS_MPPE_RECV_KEY: 657 if (radius_setmppekeys2(vp, req_info) < 0) { 658 slprintf(msg, BUF_LEN, 659 "RADIUS: bad MS-MPPE-%s-Key attribute", 660 (vp->attribute == PW_MS_MPPE_SEND_KEY)? 661 "Send": "Recv"); 662 return -1; 663 } 664 mppe_enc_keys = 1; 665 break; 666 667 case PW_MS_MPPE_ENCRYPTION_POLICY: 668 mppe_enc_policy = vp->lvalue; /* save for later */ 669 break; 670 671 case PW_MS_MPPE_ENCRYPTION_TYPES: 672 mppe_enc_types = vp->lvalue; /* save for later */ 673 break; 674 675#endif /* MPPE */ 676#if 0 677 case PW_MS_PRIMARY_DNS_SERVER: 678 case PW_MS_SECONDARY_DNS_SERVER: 679 case PW_MS_PRIMARY_NBNS_SERVER: 680 case PW_MS_SECONDARY_NBNS_SERVER: 681 break; 682#endif 683 } 684#endif /* CHAPMS */ 685 } 686 vp = vp->next; 687 } 688 689 /* Require a valid MS-CHAP2-SUCCESS for MS-CHAPv2 auth */ 690 if (digest && (digest->code == CHAP_MICROSOFT_V2) && !ms_chap2_success) 691 return -1; 692 693#ifdef MPPE 694 /* 695 * Require both policy and key attributes to indicate a valid key. 696 * Note that if the policy value was '0' we don't set the key! 697 */ 698 if (mppe_enc_policy && mppe_enc_keys) { 699 mppe_keys_set = 1; 700 /* Set/modify allowed encryption types. */ 701 if (mppe_enc_types) 702 set_mppe_enc_types(mppe_enc_policy, mppe_enc_types); 703 } 704#endif 705 706 return 0; 707} 708 709#ifdef MPPE 710/********************************************************************** 711* %FUNCTION: radius_setmppekeys 712* %ARGUMENTS: 713* vp -- value pair holding MS-CHAP-MPPE-KEYS attribute 714* req_info -- radius request information used for encryption 715* %RETURNS: 716* >= 0 on success; -1 on failure 717* %DESCRIPTION: 718* Decrypt the "key" provided by the RADIUS server for MPPE encryption. 719* See RFC 2548. 720***********************************************************************/ 721static int 722radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, 723 unsigned char *challenge) 724{ 725 int i; 726 MD5_CTX Context; 727 u_char plain[32]; 728 u_char buf[16]; 729 730 if (vp->lvalue != 32) { 731 error("RADIUS: Incorrect attribute length (%d) for MS-CHAP-MPPE-Keys", 732 vp->lvalue); 733 return -1; 734 } 735 736 memcpy(plain, vp->strvalue, sizeof(plain)); 737 738 MD5_Init(&Context); 739 MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); 740 MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); 741 MD5_Final(buf, &Context); 742 743 for (i = 0; i < 16; i++) 744 plain[i] ^= buf[i]; 745 746 MD5_Init(&Context); 747 MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); 748 MD5_Update(&Context, vp->strvalue, 16); 749 MD5_Final(buf, &Context); 750 751 for(i = 0; i < 16; i++) 752 plain[i + 16] ^= buf[i]; 753 754 /* 755 * Annoying. The "key" returned is just the NTPasswordHashHash, which 756 * the NAS (us) doesn't need; we only need the start key. So we have 757 * to generate the start key, sigh. NB: We do not support the LM-Key. 758 */ 759 mppe_set_keys(challenge, &plain[8]); 760 761 return 0; 762} 763 764/********************************************************************** 765* %FUNCTION: radius_setmppekeys2 766* %ARGUMENTS: 767* vp -- value pair holding MS-MPPE-SEND-KEY or MS-MPPE-RECV-KEY attribute 768* req_info -- radius request information used for encryption 769* %RETURNS: 770* >= 0 on success; -1 on failure 771* %DESCRIPTION: 772* Decrypt the key provided by the RADIUS server for MPPE encryption. 773* See RFC 2548. 774***********************************************************************/ 775static int 776radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info) 777{ 778 int i; 779 MD5_CTX Context; 780 u_char *salt = vp->strvalue; 781 u_char *crypt = vp->strvalue + 2; 782 u_char plain[32]; 783 u_char buf[MD5_HASH_SIZE]; 784 char *type = "Send"; 785 786 if (vp->attribute == PW_MS_MPPE_RECV_KEY) 787 type = "Recv"; 788 789 if (vp->lvalue != 34) { 790 error("RADIUS: Incorrect attribute length (%d) for MS-MPPE-%s-Key", 791 vp->lvalue, type); 792 return -1; 793 } 794 795 if ((salt[0] & 0x80) == 0) { 796 error("RADIUS: Illegal salt value for MS-MPPE-%s-Key attribute", type); 797 return -1; 798 } 799 800 memcpy(plain, crypt, 32); 801 802 MD5_Init(&Context); 803 MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); 804 MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); 805 MD5_Update(&Context, salt, 2); 806 MD5_Final(buf, &Context); 807 808 for (i = 0; i < 16; i++) 809 plain[i] ^= buf[i]; 810 811 if (plain[0] != sizeof(mppe_send_key) /* 16 */) { 812 error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute", 813 (int) plain[0], type); 814 return -1; 815 } 816 817 MD5_Init(&Context); 818 MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); 819 MD5_Update(&Context, crypt, 16); 820 MD5_Final(buf, &Context); 821 822 plain[16] ^= buf[0]; /* only need the first byte */ 823 824 if (vp->attribute == PW_MS_MPPE_SEND_KEY) 825 memcpy(mppe_send_key, plain + 1, 16); 826 else 827 memcpy(mppe_recv_key, plain + 1, 16); 828 829 return 0; 830} 831#endif /* MPPE */ 832 833/********************************************************************** 834* %FUNCTION: radius_acct_start 835* %ARGUMENTS: 836* None 837* %RETURNS: 838* Nothing 839* %DESCRIPTION: 840* Sends a "start" accounting message to the RADIUS server. 841***********************************************************************/ 842static void 843radius_acct_start(void) 844{ 845 UINT4 av_type; 846 int result; 847 VALUE_PAIR *send = NULL; 848 ipcp_options *ho = &ipcp_hisoptions[0]; 849 u_int32_t hisaddr; 850 851 if (!rstate.initialized) { 852 return; 853 } 854 855 rstate.start_time = time(NULL); 856 857 strncpy(rstate.session_id, rc_mksid(), sizeof(rstate.session_id)); 858 859 rc_avpair_add(&send, PW_ACCT_SESSION_ID, 860 rstate.session_id, 0, VENDOR_NONE); 861 rc_avpair_add(&send, PW_USER_NAME, 862 rstate.user, 0, VENDOR_NONE); 863 864 if (rstate.class_len > 0) 865 rc_avpair_add(&send, PW_CLASS, 866 rstate.class, rstate.class_len, VENDOR_NONE); 867 868 av_type = PW_STATUS_START; 869 rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); 870 871 av_type = PW_FRAMED; 872 rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE); 873 874 av_type = PW_PPP; 875 rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE); 876 877 if (*remote_number) { 878 rc_avpair_add(&send, PW_CALLING_STATION_ID, 879 remote_number, 0, VENDOR_NONE); 880 } else if (ipparam) 881 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 882 883 av_type = PW_RADIUS; 884 rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE); 885 886 887 av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) ); 888 rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE); 889 890 hisaddr = ho->hisaddr; 891 av_type = htonl(hisaddr); 892 rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); 893 894 /* Add user specified vp's */ 895 if (rstate.avp) 896 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 897 898 if (rstate.acctserver) { 899 result = rc_acct_using_server(rstate.acctserver, 900 rstate.client_port, send); 901 } else { 902 result = rc_acct(rstate.client_port, send); 903 } 904 905 rc_avpair_free(send); 906 907 if (result != OK_RC) { 908 /* RADIUS server could be down so make this a warning */ 909 syslog(LOG_WARNING, 910 "Accounting START failed for %s", rstate.user); 911 } else { 912 rstate.accounting_started = 1; 913 /* Kick off periodic accounting reports */ 914 if (rstate.acct_interim_interval) { 915 TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); 916 } 917 } 918} 919 920/********************************************************************** 921* %FUNCTION: radius_acct_stop 922* %ARGUMENTS: 923* None 924* %RETURNS: 925* Nothing 926* %DESCRIPTION: 927* Sends a "stop" accounting message to the RADIUS server. 928***********************************************************************/ 929static void 930radius_acct_stop(void) 931{ 932 UINT4 av_type; 933 VALUE_PAIR *send = NULL; 934 ipcp_options *ho = &ipcp_hisoptions[0]; 935 u_int32_t hisaddr; 936 int result; 937 938 if (!rstate.initialized) { 939 return; 940 } 941 942 if (!rstate.accounting_started) { 943 return; 944 } 945 946 rstate.accounting_started = 0; 947 rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 948 0, VENDOR_NONE); 949 950 rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE); 951 952 av_type = PW_STATUS_STOP; 953 rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); 954 955 av_type = PW_FRAMED; 956 rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE); 957 958 av_type = PW_PPP; 959 rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE); 960 961 av_type = PW_RADIUS; 962 rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE); 963 964 965 if (link_stats_valid) { 966 av_type = link_connect_time; 967 rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE); 968 969 av_type = link_stats.bytes_out; 970 rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE); 971 972 av_type = link_stats.bytes_in; 973 rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE); 974 975 av_type = link_stats.pkts_out; 976 rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE); 977 978 av_type = link_stats.pkts_in; 979 rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE); 980 } 981 982 if (*remote_number) { 983 rc_avpair_add(&send, PW_CALLING_STATION_ID, 984 remote_number, 0, VENDOR_NONE); 985 } else if (ipparam) 986 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 987 988 av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) ); 989 rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE); 990 991 av_type = PW_NAS_ERROR; 992 switch( status ) { 993 case EXIT_OK: 994 case EXIT_USER_REQUEST: 995 av_type = PW_USER_REQUEST; 996 break; 997 998 case EXIT_HANGUP: 999 case EXIT_PEER_DEAD: 1000 case EXIT_CONNECT_FAILED: 1001 av_type = PW_LOST_CARRIER; 1002 break; 1003 1004 case EXIT_INIT_FAILED: 1005 case EXIT_OPEN_FAILED: 1006 case EXIT_LOCK_FAILED: 1007 case EXIT_PTYCMD_FAILED: 1008 av_type = PW_PORT_ERROR; 1009 break; 1010 1011 case EXIT_PEER_AUTH_FAILED: 1012 case EXIT_AUTH_TOPEER_FAILED: 1013 case EXIT_NEGOTIATION_FAILED: 1014 case EXIT_CNID_AUTH_FAILED: 1015 av_type = PW_SERVICE_UNAVAILABLE; 1016 break; 1017 1018 case EXIT_IDLE_TIMEOUT: 1019 av_type = PW_ACCT_IDLE_TIMEOUT; 1020 break; 1021 1022 case EXIT_CALLBACK: 1023 av_type = PW_CALLBACK; 1024 break; 1025 1026 case EXIT_CONNECT_TIME: 1027 av_type = PW_ACCT_SESSION_TIMEOUT; 1028 break; 1029 1030#ifdef MAXOCTETS 1031 case EXIT_TRAFFIC_LIMIT: 1032 av_type = PW_NAS_REQUEST; 1033 break; 1034#endif 1035 1036 default: 1037 av_type = PW_NAS_ERROR; 1038 break; 1039 } 1040 rc_avpair_add(&send, PW_ACCT_TERMINATE_CAUSE, &av_type, 0, VENDOR_NONE); 1041 1042 hisaddr = ho->hisaddr; 1043 av_type = htonl(hisaddr); 1044 rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); 1045 1046 /* Add user specified vp's */ 1047 if (rstate.avp) 1048 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 1049 1050 if (rstate.acctserver) { 1051 result = rc_acct_using_server(rstate.acctserver, 1052 rstate.client_port, send); 1053 } else { 1054 result = rc_acct(rstate.client_port, send); 1055 } 1056 1057 if (result != OK_RC) { 1058 /* RADIUS server could be down so make this a warning */ 1059 syslog(LOG_WARNING, 1060 "Accounting STOP failed for %s", rstate.user); 1061 } 1062 rc_avpair_free(send); 1063} 1064 1065/********************************************************************** 1066* %FUNCTION: radius_acct_interim 1067* %ARGUMENTS: 1068* None 1069* %RETURNS: 1070* Nothing 1071* %DESCRIPTION: 1072* Sends an interim accounting message to the RADIUS server 1073***********************************************************************/ 1074static void 1075radius_acct_interim(void *ignored) 1076{ 1077 UINT4 av_type; 1078 VALUE_PAIR *send = NULL; 1079 ipcp_options *ho = &ipcp_hisoptions[0]; 1080 u_int32_t hisaddr; 1081 int result; 1082 1083 if (!rstate.initialized) { 1084 return; 1085 } 1086 1087 if (!rstate.accounting_started) { 1088 return; 1089 } 1090 1091 rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 1092 0, VENDOR_NONE); 1093 1094 rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE); 1095 1096 av_type = PW_STATUS_ALIVE; 1097 rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); 1098 1099 av_type = PW_FRAMED; 1100 rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE); 1101 1102 av_type = PW_PPP; 1103 rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE); 1104 1105 av_type = PW_RADIUS; 1106 rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE); 1107 1108 /* Update link stats */ 1109 update_link_stats(0); 1110 1111 if (link_stats_valid) { 1112 link_stats_valid = 0; /* Force later code to update */ 1113 1114 av_type = link_connect_time; 1115 rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE); 1116 1117 av_type = link_stats.bytes_out; 1118 rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE); 1119 1120 av_type = link_stats.bytes_in; 1121 rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE); 1122 1123 av_type = link_stats.pkts_out; 1124 rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE); 1125 1126 av_type = link_stats.pkts_in; 1127 rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE); 1128 } 1129 1130 if (*remote_number) { 1131 rc_avpair_add(&send, PW_CALLING_STATION_ID, 1132 remote_number, 0, VENDOR_NONE); 1133 } else if (ipparam) 1134 rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); 1135 1136 av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) ); 1137 rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE); 1138 1139 hisaddr = ho->hisaddr; 1140 av_type = htonl(hisaddr); 1141 rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); 1142 1143 /* Add user specified vp's */ 1144 if (rstate.avp) 1145 rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); 1146 1147 if (rstate.acctserver) { 1148 result = rc_acct_using_server(rstate.acctserver, 1149 rstate.client_port, send); 1150 } else { 1151 result = rc_acct(rstate.client_port, send); 1152 } 1153 1154 if (result != OK_RC) { 1155 /* RADIUS server could be down so make this a warning */ 1156 syslog(LOG_WARNING, 1157 "Interim accounting failed for %s", rstate.user); 1158 } 1159 rc_avpair_free(send); 1160 1161 /* Schedule another one */ 1162 TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); 1163} 1164 1165/********************************************************************** 1166* %FUNCTION: radius_ip_up 1167* %ARGUMENTS: 1168* opaque -- ignored 1169* arg -- ignored 1170* %RETURNS: 1171* Nothing 1172* %DESCRIPTION: 1173* Called when IPCP is up. We'll do a start-accounting record. 1174***********************************************************************/ 1175static void 1176radius_ip_up(void *opaque, int arg) 1177{ 1178 radius_acct_start(); 1179} 1180 1181/********************************************************************** 1182* %FUNCTION: radius_ip_down 1183* %ARGUMENTS: 1184* opaque -- ignored 1185* arg -- ignored 1186* %RETURNS: 1187* Nothing 1188* %DESCRIPTION: 1189* Called when IPCP is down. We'll do a stop-accounting record. 1190***********************************************************************/ 1191static void 1192radius_ip_down(void *opaque, int arg) 1193{ 1194 radius_acct_stop(); 1195} 1196 1197/********************************************************************** 1198* %FUNCTION: radius_init 1199* %ARGUMENTS: 1200* msg -- buffer of size BUF_LEN for error message 1201* %RETURNS: 1202* negative on failure; non-negative on success 1203* %DESCRIPTION: 1204* Initializes radiusclient library 1205***********************************************************************/ 1206static int 1207radius_init(char *msg) 1208{ 1209 if (rstate.initialized) { 1210 return 0; 1211 } 1212 1213 if (config_file && *config_file) { 1214 strlcpy(rstate.config_file, config_file, MAXPATHLEN-1); 1215 } 1216 1217 rstate.initialized = 1; 1218 1219 if (rc_read_config(rstate.config_file) != 0) { 1220 slprintf(msg, BUF_LEN, "RADIUS: Can't read config file %s", 1221 rstate.config_file); 1222 return -1; 1223 } 1224 1225 if (rc_read_dictionary(rc_conf_str("dictionary")) != 0) { 1226 slprintf(msg, BUF_LEN, "RADIUS: Can't read dictionary file %s", 1227 rc_conf_str("dictionary")); 1228 return -1; 1229 } 1230 1231 if (rc_read_mapfile(rc_conf_str("mapfile")) != 0) { 1232 slprintf(msg, BUF_LEN, "RADIUS: Can't read map file %s", 1233 rc_conf_str("mapfile")); 1234 return -1; 1235 } 1236 1237 /* Add av pairs saved during option parsing */ 1238 while (avpopt) { 1239 struct avpopt *n = avpopt->next; 1240 1241 rc_avpair_parse(avpopt->vpstr, &rstate.avp); 1242 free(avpopt->vpstr); 1243 free(avpopt); 1244 avpopt = n; 1245 } 1246 return 0; 1247} 1248 1249/********************************************************************** 1250* %FUNCTION: get_client_port 1251* %ARGUMENTS: 1252* ifname -- PPP interface name (e.g. "ppp7") 1253* %RETURNS: 1254* The NAS port number (e.g. 7) 1255* %DESCRIPTION: 1256* Extracts the port number from the interface name 1257***********************************************************************/ 1258static int 1259get_client_port(char *ifname) 1260{ 1261 int port; 1262 if (sscanf(ifname, "ppp%d", &port) == 1) { 1263 return port; 1264 } 1265 return rc_map2id(ifname); 1266} 1267 1268/********************************************************************** 1269* %FUNCTION: radius_allowed_address 1270* %ARGUMENTS: 1271* addr -- IP address 1272* %RETURNS: 1273* 1 if we're allowed to use that IP address; 0 if not; -1 if we do 1274* not know. 1275***********************************************************************/ 1276static int 1277radius_allowed_address(u_int32_t addr) 1278{ 1279 ipcp_options *wo = &ipcp_wantoptions[0]; 1280 1281 if (!rstate.choose_ip) { 1282 /* If RADIUS server said any address is OK, then fine... */ 1283 if (rstate.any_ip_addr_ok) { 1284 return 1; 1285 } 1286 1287 /* Sigh... if an address was supplied for remote host in pppd 1288 options, it has to match that. */ 1289 if (wo->hisaddr != 0 && wo->hisaddr == addr) { 1290 return 1; 1291 } 1292 1293 return 0; 1294 } 1295 if (addr == rstate.ip_addr) return 1; 1296 return 0; 1297} 1298 1299/* Useful for other plugins */ 1300char *radius_logged_in_user(void) 1301{ 1302 return rstate.user; 1303} 1304