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 (at) elgo.si> 12 * Copyright (C) 1996, Lars Fenneberg <in5y050 (at) public.uni-hamburg.de> 13 * Copyright (C) 1997, Miguel A.L. Paraz <map (at) iphil.net> 14 * 15 * Uses radiusclient library, which is: 16 * Copyright (C) 1995,1996,1997,1998 Lars Fenneberg <lf (at) elemental.net> 17 * Copyright (C) 2002 Roaring Penguin Software Inc. 18 * 19 * MPPE support is by Ralf Hofmann, <ralf.hofmann (at) elvido.net>, with 20 * modification from Frank Cusack, <frank (at) 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 ***********************************************************************/ 26 static 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 51 static char *config_file = NULL; 52 static int add_avp(char **); 53 static struct avpopt { 54 char *vpstr; 55 struct avpopt *next; 56 } *avpopt = NULL; 57 static bool portnummap = 0; 58 59 static 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 69 static int radius_secret_check(void); 70 static int radius_pap_auth(char *user, 71 char *passwd, 72 char **msgp, 73 struct wordlist **paddrs, 74 struct wordlist **popts); 75 static 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 81 static void radius_ip_up(void *opaque, int arg); 82 static void radius_ip_down(void *opaque, int arg); 83 static void make_username_realm(char *user); 84 static 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); 88 static void radius_choose_ip(u_int32_t *addrp); 89 static int radius_init(char *msg); 90 static int get_client_port(char *ifname); 91 static int radius_allowed_address(u_int32_t addr); 92 static void radius_acct_interim(void *); 93 #ifdef MPPE 94 static int radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, 95 unsigned char *); 96 static 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 107 struct 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 127 void (*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 */ 131 void (*radius_pre_auth_hook)(char const *user, 132 SERVER **authserver, 133 SERVER **acctserver) = NULL; 134 135 static struct radius_state rstate; 136 137 char pppd_version[] = VERSION; 138 139 /********************************************************************** 140 * %FUNCTION: plugin_init 141 * %ARGUMENTS: 142 * None 143 * %RETURNS: 144 * Nothing 145 * %DESCRIPTION: 146 * Initializes RADIUS plugin. 147 ***********************************************************************/ 148 void 149 plugin_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 ***********************************************************************/ 182 static int 183 add_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 ***********************************************************************/ 205 static int 206 radius_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 ***********************************************************************/ 220 static void 221 radius_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 ***********************************************************************/ 241 static int 242 radius_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 ***********************************************************************/ 331 static int 332 radius_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 ***********************************************************************/ 510 static void 511 make_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 ***********************************************************************/ 541 static int 542 radius_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 ***********************************************************************/ 728 static int 729 radius_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 ***********************************************************************/ 782 static int 783 radius_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 ***********************************************************************/ 849 static void 850 radius_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 ***********************************************************************/ 936 static void 937 radius_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 ***********************************************************************/ 1077 static void 1078 radius_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 ***********************************************************************/ 1178 static void 1179 radius_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 ***********************************************************************/ 1194 static void 1195 radius_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 ***********************************************************************/ 1209 static int 1210 radius_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 ***********************************************************************/ 1261 static int 1262 get_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 ***********************************************************************/ 1279 static int 1280 radius_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 */ 1303 char *radius_logged_in_user(void) 1304 { 1305 return rstate.user; 1306 } 1307