Home | History | Annotate | Download | only in radius
      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