X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fplugins%2Fradius%2Fradius.c;h=48882a9e1c84be070d6a56e21e9c01b7704280e4;hb=e50870a901749c7390109404e90c095ea3ef7072;hp=6d65b96e22b7e86e3a63be6afc310763e72b6de1;hpb=56e2bdf2bad880f575f01a8acee94439a6786726;p=ppp.git diff --git a/pppd/plugins/radius/radius.c b/pppd/plugins/radius/radius.c index 6d65b96..48882a9 100644 --- a/pppd/plugins/radius/radius.c +++ b/pppd/plugins/radius/radius.c @@ -24,7 +24,7 @@ * ***********************************************************************/ static char const RCSID[] = -"$Id: radius.c,v 1.12 2002/07/24 20:13:12 dfs Exp $"; +"$Id: radius.c,v 1.19 2002/12/23 23:24:37 fcusack Exp $"; #include "pppd.h" #include "chap.h" @@ -40,13 +40,20 @@ static char const RCSID[] = #include #include #include +#include #define BUF_LEN 1024 static char *config_file = NULL; +static int add_avp(char **); +static struct avpopt { + char *vpstr; + struct avpopt *next; +} *avpopt = NULL; static option_t Options[] = { { "radius-config-file", o_string, &config_file }, + { "avpair", o_special, add_avp }, { NULL } }; @@ -70,6 +77,7 @@ static void radius_choose_ip(u_int32_t *addrp); static int radius_init(char *msg); static int get_client_port(char *ifname); static int radius_allowed_address(u_int32_t addr); +static void radius_acct_interim(void *); #ifdef MPPE static int radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, chap_state *); @@ -80,6 +88,10 @@ static int radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info); #define MAXSESSIONID 32 #endif +#ifndef MAXCLASSLEN +#define MAXCLASSLEN 500 +#endif + struct radius_state { int accounting_started; int initialized; @@ -92,8 +104,12 @@ struct radius_state { char config_file[MAXPATHLEN]; char session_id[MAXSESSIONID + 1]; time_t start_time; + int acct_interim_interval; SERVER *authserver; /* Authentication server to use */ SERVER *acctserver; /* Accounting server to use */ + int class_len; + char class[MAXCLASSLEN]; + VALUE_PAIR *avp; /* Additional (user supplied) vp's to send to server */ }; void (*radius_attributes_hook)(VALUE_PAIR *) = NULL; @@ -142,6 +158,28 @@ plugin_init(void) info("RADIUS plugin initialized."); } +/********************************************************************** +* %FUNCTION: add_avp +* %ARGUMENTS: +* argv -- the pair to add +* %RETURNS: +* 1 +* %DESCRIPTION: +* Adds an av pair to be passed on to the RADIUS server on each request. +***********************************************************************/ +static int +add_avp(char **argv) +{ + struct avpopt *p = malloc(sizeof(struct avpopt)); + + /* Append to a list of vp's for later parsing */ + p->vpstr = strdup(*argv); + p->next = avpopt; + avpopt = p; + + return 1; +} + /********************************************************************** * %FUNCTION: radius_secret_check * %ARGUMENTS: @@ -236,6 +274,10 @@ radius_pap_auth(char *user, VENDOR_NONE); } + /* Add user specified vp's */ + if (rstate.avp) + rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); + if (rstate.authserver) { result = rc_auth_using_server(rstate.authserver, rstate.client_port, send, @@ -386,9 +428,17 @@ radius_chap_auth(char *user, break; } #endif + } + if (*remote_number) { + rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, + VENDOR_NONE); } + /* Add user specified vp's */ + if (rstate.avp) + rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); + /* * make authentication with RADIUS server */ @@ -511,9 +561,19 @@ radius_setparams(chap_state *cstate, VALUE_PAIR *vp, char *msg, break; case PW_OCTETS_DIRECTION: /* Session traffic limit direction check */ - maxoctets_dir = ( vp->lvalue > 4 ) 0 : vp->lvalue ; + maxoctets_dir = ( vp->lvalue > 4 ) ? 0 : vp->lvalue ; + break; +#endif + case PW_ACCT_INTERIM_INTERVAL: + /* Send accounting updates every few seconds */ + rstate.acct_interim_interval = vp->lvalue; + /* RFC says it MUST NOT be less than 60 seconds */ + /* We use "0" to signify not sending updates */ + if (rstate.acct_interim_interval && + rstate.acct_interim_interval < 60) { + rstate.acct_interim_interval = 60; + } break; -#endif case PW_FRAMED_IP_ADDRESS: /* seting up remote IP addresses */ remote = vp->lvalue; @@ -532,7 +592,16 @@ radius_setparams(chap_state *cstate, VALUE_PAIR *vp, char *msg, rstate.ip_addr = remote; } break; + case PW_CLASS: + /* Save Class attribute to pass it in accounting request */ + if (vp->lvalue <= MAXCLASSLEN) { + rstate.class_len=vp->lvalue; + memcpy(rstate.class, vp->strvalue, rstate.class_len); + } /* else too big for our buffer - ignore it */ + break; } + + #ifdef CHAPMS } else if (vp->vendorcode == VENDOR_MICROSOFT) { switch (vp->attribute) { @@ -640,6 +709,7 @@ radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, chap_state *cstate) * to generate the start key, sigh. NB: We do not support the LM-Key. */ mppe_set_keys(cstate->challenge, &plain[8]); + mppe_keys_set = 1; return 0; } @@ -708,6 +778,7 @@ radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info) memcpy(mppe_send_key, plain + 1, 16); else memcpy(mppe_recv_key, plain + 1, 16); + mppe_keys_set = 1; return 0; } @@ -744,6 +815,10 @@ radius_acct_start(void) rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE); + if (rstate.class_len > 0) + rc_avpair_add(&send, PW_CLASS, + rstate.class, rstate.class_len, VENDOR_NONE); + av_type = PW_STATUS_START; rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); @@ -769,6 +844,10 @@ radius_acct_start(void) av_type = htonl(hisaddr); rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); + /* Add user specified vp's */ + if (rstate.avp) + rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); + if (rstate.acctserver) { result = rc_acct_using_server(rstate.acctserver, rstate.client_port, send); @@ -784,6 +863,10 @@ radius_acct_start(void) "Accounting START failed for %s", rstate.user); } else { rstate.accounting_started = 1; + /* Kick off periodic accounting reports */ + if (rstate.acct_interim_interval) { + TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); + } } } @@ -861,6 +944,10 @@ radius_acct_stop(void) av_type = htonl(hisaddr); rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); + /* Add user specified vp's */ + if (rstate.avp) + rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); + if (rstate.acctserver) { result = rc_acct_using_server(rstate.acctserver, rstate.client_port, send); @@ -886,7 +973,7 @@ radius_acct_stop(void) * Sends an interim accounting message to the RADIUS server ***********************************************************************/ static void -radius_acct_interim(void) +radius_acct_interim(void *ignored) { UINT4 av_type; VALUE_PAIR *send = NULL; @@ -953,6 +1040,10 @@ radius_acct_interim(void) av_type = htonl(hisaddr); rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE); + /* Add user specified vp's */ + if (rstate.avp) + rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); + if (rstate.acctserver) { result = rc_acct_using_server(rstate.acctserver, rstate.client_port, send); @@ -966,6 +1057,9 @@ radius_acct_interim(void) "Interim accounting failed for %s", rstate.user); } rc_avpair_free(send); + + /* Schedule another one */ + TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); } /********************************************************************** @@ -1039,6 +1133,16 @@ radius_init(char *msg) rc_conf_str("mapfile")); return -1; } + + /* Add av pairs saved during option parsing */ + while (avpopt) { + struct avpopt *n = avpopt->next; + + rc_avpair_parse(avpopt->vpstr, &rstate.avp); + free(avpopt->vpstr); + free(avpopt); + avpopt = n; + } return 0; }