X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;ds=sidebyside;f=pppd%2Fplugins%2Fradius%2Fradius.c;h=43238200eb8a6eca256d1fa5a476c4588bf5c02b;hb=a8e48b736c49bd1f48fc8ca617e9c3eda74e980c;hp=264b0ade4a0391eeb7e520f39f563a02350599bb;hpb=efc4e8025a12a2337b6f0116cce491d38323f2f0;p=ppp.git diff --git a/pppd/plugins/radius/radius.c b/pppd/plugins/radius/radius.c index 264b0ad..4323820 100644 --- a/pppd/plugins/radius/radius.c +++ b/pppd/plugins/radius/radius.c @@ -24,13 +24,18 @@ * ***********************************************************************/ static char const RCSID[] = -"$Id: radius.c,v 1.26 2004/10/28 00:22:54 paulus Exp $"; +"$Id: radius.c,v 1.32 2008/05/26 09:18:08 paulus Exp $"; + +#ifdef HAVE_CONFIG_H +#include +#endif #include "pppd.h" #include "chap-new.h" #ifdef CHAPMS #include "chap_ms.h" #ifdef MPPE +#include "mppe.h" #include "md5.h" #endif #endif @@ -41,11 +46,15 @@ static char const RCSID[] = #include #include #include +#include +#include #define BUF_LEN 1024 #define MD5_HASH_SIZE 16 +#define MSDNS 1 + static char *config_file = NULL; static int add_avp(char **); static struct avpopt { @@ -103,7 +112,6 @@ static int radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info); #endif struct radius_state { - int accounting_started; int initialized; int client_port; int choose_ip; @@ -282,7 +290,8 @@ radius_pap_auth(char *user, if (*remote_number) { rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, VENDOR_NONE); - } + } else if (ipparam) + rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); /* Add user specified vp's */ if (rstate.avp) @@ -407,18 +416,14 @@ radius_chap_verify(char *user, char *ourname, int id, case CHAP_MICROSOFT: { /* MS-CHAP-Challenge and MS-CHAP-Response */ - MS_ChapResponse *rmd = (MS_ChapResponse *) response; u_char *p = cpassword; if (response_len != MS_CHAP_RESPONSE_LEN) return 0; *p++ = id; /* The idiots use a different field order in RADIUS than PPP */ - memcpy(p, rmd->UseNT, sizeof(rmd->UseNT)); - p += sizeof(rmd->UseNT); - memcpy(p, rmd->LANManResp, sizeof(rmd->LANManResp)); - p += sizeof(rmd->LANManResp); - memcpy(p, rmd->NTResp, sizeof(rmd->NTResp)); + *p++ = response[MS_CHAP_USENT]; + memcpy(p, response, MS_CHAP_LANMANRESP_LEN + MS_CHAP_NTRESP_LEN); rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE, challenge, challenge_len, VENDOR_MICROSOFT); @@ -430,20 +435,15 @@ radius_chap_verify(char *user, char *ourname, int id, case CHAP_MICROSOFT_V2: { /* MS-CHAP-Challenge and MS-CHAP2-Response */ - MS_Chap2Response *rmd = (MS_Chap2Response *) response; u_char *p = cpassword; if (response_len != MS_CHAP2_RESPONSE_LEN) return 0; *p++ = id; /* The idiots use a different field order in RADIUS than PPP */ - memcpy(p, rmd->Flags, sizeof(rmd->Flags)); - p += sizeof(rmd->Flags); - memcpy(p, rmd->PeerChallenge, sizeof(rmd->PeerChallenge)); - p += sizeof(rmd->PeerChallenge); - memcpy(p, rmd->Reserved, sizeof(rmd->Reserved)); - p += sizeof(rmd->Reserved); - memcpy(p, rmd->NTResp, sizeof(rmd->NTResp)); + *p++ = response[MS_CHAP2_FLAGS]; + memcpy(p, response, (MS_CHAP2_PEER_CHAL_LEN + MS_CHAP2_RESERVED_LEN + + MS_CHAP2_NTRESP_LEN)); rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE, challenge, challenge_len, VENDOR_MICROSOFT); @@ -457,7 +457,8 @@ radius_chap_verify(char *user, char *ourname, int id, if (*remote_number) { rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, VENDOR_NONE); - } + } else if (ipparam) + rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); /* Add user specified vp's */ if (rstate.avp) @@ -476,6 +477,8 @@ radius_chap_verify(char *user, char *ourname, int id, req_info); } + strlcpy(message, radius_msg, message_space); + if (result == OK_RC) { if (!rstate.done_chap_once) { if (radius_setparams(received, radius_msg, req_info, digest, @@ -546,6 +549,14 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, int mppe_enc_policy = 0; int mppe_enc_types = 0; #endif +#ifdef MSDNS + ipcp_options *wo = &ipcp_wantoptions[0]; + ipcp_options *ao = &ipcp_allowoptions[0]; + int got_msdns_1 = 0; + int got_msdns_2 = 0; + int got_wins_1 = 0; + int got_wins_2 = 0; +#endif /* Send RADIUS attributes to anyone else who might be interested */ if (radius_attributes_hook) { @@ -584,6 +595,18 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, /* Session timeout */ maxconnect = vp->lvalue; break; + case PW_FILTER_ID: + /* packet filter, will be handled via ip-(up|down) script */ + script_setenv("RADIUS_FILTER_ID", (char*) vp->strvalue, 1); + break; + case PW_FRAMED_ROUTE: + /* route, will be handled via ip-(up|down) script */ + script_setenv("RADIUS_FRAMED_ROUTE", (char*) vp->strvalue, 1); + break; + case PW_IDLE_TIMEOUT: + /* idle parameter */ + idle_time_limit = vp->lvalue; + break; #ifdef MAXOCTETS case PW_SESSION_OCTETS_LIMIT: /* Session traffic limit */ @@ -622,6 +645,9 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, rstate.ip_addr = remote; } break; + case PW_NAS_IP_ADDRESS: + wo->ouraddr = htonl(vp->lvalue); + break; case PW_CLASS: /* Save Class attribute to pass it in accounting request */ if (vp->lvalue <= MAXCLASSLEN) { @@ -629,19 +655,22 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, memcpy(rstate.class, vp->strvalue, rstate.class_len); } /* else too big for our buffer - ignore it */ break; + case PW_FRAMED_MTU: + netif_set_mtu(rstate.client_port,MIN(netif_get_mtu(rstate.client_port),vp->lvalue)); + break; } -#ifdef CHAPMS } else if (vp->vendorcode == VENDOR_MICROSOFT) { +#ifdef CHAPMS switch (vp->attribute) { case PW_MS_CHAP2_SUCCESS: - if ((vp->lvalue != 43) || strncmp(vp->strvalue + 1, "S=", 2)) { + if ((vp->lvalue != 43) || strncmp((char*) vp->strvalue + 1, "S=", 2)) { slprintf(msg,BUF_LEN,"RADIUS: bad MS-CHAP2-Success packet"); return -1; } if (message != NULL) - strlcpy(message, vp->strvalue + 1, message_space); + strlcpy(message, (char*) vp->strvalue + 1, message_space); ms_chap2_success = 1; break; @@ -676,13 +705,32 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, break; #endif /* MPPE */ -#if 0 +#ifdef MSDNS case PW_MS_PRIMARY_DNS_SERVER: + ao->dnsaddr[0] = htonl(vp->lvalue); + got_msdns_1 = 1; + if (!got_msdns_2) + ao->dnsaddr[1] = ao->dnsaddr[0]; + break; case PW_MS_SECONDARY_DNS_SERVER: + ao->dnsaddr[1] = htonl(vp->lvalue); + got_msdns_2 = 1; + if (!got_msdns_1) + ao->dnsaddr[0] = ao->dnsaddr[1]; + break; case PW_MS_PRIMARY_NBNS_SERVER: + ao->winsaddr[0] = htonl(vp->lvalue); + got_wins_1 = 1; + if (!got_wins_2) + ao->winsaddr[1] = ao->winsaddr[0]; + break; case PW_MS_SECONDARY_NBNS_SERVER: + ao->winsaddr[1] = htonl(vp->lvalue); + got_wins_2 = 1; + if (!got_wins_1) + ao->winsaddr[0] = ao->winsaddr[1]; break; -#endif +#endif /* MSDNS */ } #endif /* CHAPMS */ } @@ -699,11 +747,12 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, * Note that if the policy value was '0' we don't set the key! */ if (mppe_enc_policy && mppe_enc_keys) { - mppe_keys_set = 1; /* Set/modify allowed encryption types. */ if (mppe_enc_types) - set_mppe_enc_types(mppe_enc_policy, mppe_enc_types); + mppe_set_enc_types(mppe_enc_policy, mppe_enc_types); + return 0; } + mppe_clear_keys(); #endif return 0; @@ -738,18 +787,18 @@ radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, memcpy(plain, vp->strvalue, sizeof(plain)); - MD5Init(&Context); - MD5Update(&Context, req_info->secret, strlen(req_info->secret)); - MD5Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); - MD5Final(buf, &Context); + MD5_Init(&Context); + MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); + MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); + MD5_Final(buf, &Context); for (i = 0; i < 16; i++) plain[i] ^= buf[i]; - MD5Init(&Context); - MD5Update(&Context, req_info->secret, strlen(req_info->secret)); - MD5Update(&Context, vp->strvalue, 16); - MD5Final(buf, &Context); + MD5_Init(&Context); + MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); + MD5_Update(&Context, vp->strvalue, 16); + MD5_Final(buf, &Context); for(i = 0; i < 16; i++) plain[i + 16] ^= buf[i]; @@ -759,7 +808,7 @@ radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, * the NAS (us) doesn't need; we only need the start key. So we have * to generate the start key, sigh. NB: We do not support the LM-Key. */ - mppe_set_keys(challenge, &plain[8]); + mppe_set_chapv1(challenge, &plain[8]); return 0; } @@ -802,32 +851,32 @@ radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info) memcpy(plain, crypt, 32); - MD5Init(&Context); - MD5Update(&Context, req_info->secret, strlen(req_info->secret)); - MD5Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); - MD5Update(&Context, salt, 2); - MD5Final(buf, &Context); + MD5_Init(&Context); + MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); + MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN); + MD5_Update(&Context, salt, 2); + MD5_Final(buf, &Context); for (i = 0; i < 16; i++) plain[i] ^= buf[i]; - if (plain[0] != sizeof(mppe_send_key) /* 16 */) { + if (plain[0] != 16) { error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute", (int) plain[0], type); return -1; } - MD5Init(&Context); - MD5Update(&Context, req_info->secret, strlen(req_info->secret)); - MD5Update(&Context, crypt, 16); - MD5Final(buf, &Context); + MD5_Init(&Context); + MD5_Update(&Context, req_info->secret, strlen(req_info->secret)); + MD5_Update(&Context, crypt, 16); + MD5_Final(buf, &Context); plain[16] ^= buf[0]; /* only need the first byte */ if (vp->attribute == PW_MS_MPPE_SEND_KEY) - memcpy(mppe_send_key, plain + 1, 16); + mppe_set_keys(plain + 1, NULL, 16); else - memcpy(mppe_recv_key, plain + 1, 16); + mppe_set_keys(NULL, plain + 1, 16); return 0; } @@ -857,7 +906,7 @@ radius_acct_start(void) rstate.start_time = time(NULL); - strncpy(rstate.session_id, rc_mksid(), sizeof(rstate.session_id)); + strlcpy(rstate.session_id, rc_mksid(), MAXSESSIONID); rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 0, VENDOR_NONE); @@ -880,7 +929,8 @@ radius_acct_start(void) if (*remote_number) { rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, VENDOR_NONE); - } + } else if (ipparam) + rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); av_type = PW_RADIUS; rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE); @@ -910,12 +960,11 @@ radius_acct_start(void) /* RADIUS server could be down so make this a warning */ syslog(LOG_WARNING, "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); - } + } + + /* Kick off periodic accounting reports */ + if (rstate.acct_interim_interval) { + TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); } } @@ -941,16 +990,18 @@ radius_acct_stop(void) return; } - if (!rstate.accounting_started) { - return; - } + if (rstate.acct_interim_interval) + UNTIMEOUT(radius_acct_interim, NULL); - rstate.accounting_started = 0; rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 0, VENDOR_NONE); 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_STOP; rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); @@ -984,7 +1035,8 @@ radius_acct_stop(void) if (*remote_number) { rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, VENDOR_NONE); - } + } else if (ipparam) + rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) ); rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE); @@ -1020,6 +1072,10 @@ radius_acct_stop(void) av_type = PW_ACCT_IDLE_TIMEOUT; break; + case EXIT_CALLBACK: + av_type = PW_CALLBACK; + break; + case EXIT_CONNECT_TIME: av_type = PW_ACCT_SESSION_TIMEOUT; break; @@ -1081,15 +1137,15 @@ radius_acct_interim(void *ignored) return; } - if (!rstate.accounting_started) { - return; - } - rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 0, VENDOR_NONE); 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_ALIVE; rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE); @@ -1127,7 +1183,8 @@ radius_acct_interim(void *ignored) if (*remote_number) { rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0, VENDOR_NONE); - } + } else if (ipparam) + rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE); av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) ); rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE);