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.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 
     53 static char *config_file = NULL;
     54 static int add_avp(char **);
     55 static struct avpopt {
     56     char *vpstr;
     57     struct avpopt *next;
     58 } *avpopt = NULL;
     59 static bool portnummap = 0;
     60 
     61 static 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 
     71 static int radius_secret_check(void);
     72 static int radius_pap_auth(char *user,
     73 			   char *passwd,
     74 			   char **msgp,
     75 			   struct wordlist **paddrs,
     76 			   struct wordlist **popts);
     77 static 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 
     83 static void radius_ip_up(void *opaque, int arg);
     84 static void radius_ip_down(void *opaque, int arg);
     85 static void make_username_realm(char *user);
     86 static 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);
     90 static void radius_choose_ip(u_int32_t *addrp);
     91 static int radius_init(char *msg);
     92 static int get_client_port(char *ifname);
     93 static int radius_allowed_address(u_int32_t addr);
     94 static void radius_acct_interim(void *);
     95 #ifdef MPPE
     96 static int radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info,
     97 			      unsigned char *);
     98 static 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 
    109 struct 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 
    129 void (*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 */
    133 void (*radius_pre_auth_hook)(char const *user,
    134 			     SERVER **authserver,
    135 			     SERVER **acctserver) = NULL;
    136 
    137 static struct radius_state rstate;
    138 
    139 char pppd_version[] = VERSION;
    140 
    141 /**********************************************************************
    142 * %FUNCTION: plugin_init
    143 * %ARGUMENTS:
    144 *  None
    145 * %RETURNS:
    146 *  Nothing
    147 * %DESCRIPTION:
    148 *  Initializes RADIUS plugin.
    149 ***********************************************************************/
    150 void
    151 plugin_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 ***********************************************************************/
    184 static int
    185 add_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 ***********************************************************************/
    207 static int
    208 radius_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 ***********************************************************************/
    222 static void
    223 radius_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 ***********************************************************************/
    243 static int
    244 radius_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 ***********************************************************************/
    333 static int
    334 radius_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 ***********************************************************************/
    505 static void
    506 make_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 ***********************************************************************/
    536 static int
    537 radius_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 ***********************************************************************/
    765 static int
    766 radius_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 ***********************************************************************/
    819 static int
    820 radius_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 ***********************************************************************/
    886 static void
    887 radius_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 ***********************************************************************/
    973 static void
    974 radius_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 ***********************************************************************/
   1121 static void
   1122 radius_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 ***********************************************************************/
   1222 static void
   1223 radius_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 ***********************************************************************/
   1238 static void
   1239 radius_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 ***********************************************************************/
   1253 static int
   1254 radius_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 ***********************************************************************/
   1305 static int
   1306 get_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 ***********************************************************************/
   1323 static int
   1324 radius_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 */
   1347 char *radius_logged_in_user(void)
   1348 {
   1349     return rstate.user;
   1350 }
   1351