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@elgo.si>
12 * Copyright (C) 1996, Lars Fenneberg <in5y050@public.uni-hamburg.de>
13 * Copyright (C) 1997, Miguel A.L. Paraz <map@iphil.net>
14 *
15 * Uses radiusclient library, which is:
16 * Copyright (C) 1995,1996,1997,1998 Lars Fenneberg <lf@elemental.net>
17 * Copyright (C) 2002 Roaring Penguin Software Inc.
18 *
19 * MPPE support is by Ralf Hofmann, <ralf.hofmann@elvido.net>, with
20 * modification from Frank Cusack, <frank@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
plugin_init(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
add_avp(char ** argv)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
radius_secret_check(void)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
radius_choose_ip(u_int32_t * addrp)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
radius_pap_auth(char * user,char * passwd,char ** msgp,struct wordlist ** paddrs,struct wordlist ** popts)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
radius_chap_verify(char * user,char * ourname,int id,struct chap_digest_type * digest,unsigned char * challenge,unsigned char * response,char * message,int message_space)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
make_username_realm(char * user)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
radius_setparams(VALUE_PAIR * vp,char * msg,REQUEST_INFO * req_info,struct chap_digest_type * digest,unsigned char * challenge,char * message,int message_space)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
radius_setmppekeys(VALUE_PAIR * vp,REQUEST_INFO * req_info,unsigned char * challenge)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
radius_setmppekeys2(VALUE_PAIR * vp,REQUEST_INFO * req_info)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
radius_acct_start(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
radius_acct_stop(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
radius_acct_interim(void * ignored)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
radius_ip_up(void * opaque,int arg)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
radius_ip_down(void * opaque,int arg)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
radius_init(char * msg)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
get_client_port(char * ifname)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
radius_allowed_address(u_int32_t addr)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 */
radius_logged_in_user(void)1347 char *radius_logged_in_user(void)
1348 {
1349 return rstate.user;
1350 }
1351