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