]> git.ozlabs.org Git - ppp.git/blob - pppd/plugins/radius/radius.c
config: Include some extra files in the tarball
[ppp.git] / pppd / plugins / radius / radius.c
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
27 #include <syslog.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #include <sys/param.h>
31 #include <string.h>
32 #include <netinet/in.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <stdbool.h>
36
37 #include <pppd/pppd.h>
38 #include <pppd/options.h>
39 #include <pppd/chap.h>
40 #include <pppd/upap.h>
41 #ifdef PPP_WITH_CHAPMS
42 #include <pppd/chap_ms.h>
43 #ifdef PPP_WITH_MPPE
44 #include <pppd/mppe.h>
45 #endif
46 #endif
47 #include <pppd/crypto.h>
48 #include <pppd/fsm.h>
49 #include <pppd/ipcp.h>
50
51 #include "radiusclient.h"
52
53 #define BUF_LEN 1024
54
55 #define MSDNS 1
56
57 static char *config_file = NULL;
58 static int add_avp(char **);
59 static struct avpopt {
60     char *vpstr;
61     struct avpopt *next;
62 } *avpopt = NULL;
63 static bool portnummap = 0;
64
65 static option_t Options[] = {
66     { "radius-config-file", o_string, &config_file },
67     { "avpair", o_special, add_avp },
68     { "map-to-ttyname", o_bool, &portnummap,
69         "Set Radius NAS-Port attribute value via libradiusclient library", OPT_PRIO | 1 },
70     { "map-to-ifname", o_bool, &portnummap,
71         "Set Radius NAS-Port attribute to number as in interface name (Default)", OPT_PRIOSUB | 0 },
72     { NULL }
73 };
74
75 static pap_check_hook_fn radius_secret_check;
76 static pap_auth_hook_fn radius_pap_auth;
77 static chap_verify_hook_fn radius_chap_verify;
78
79 static void radius_ip_up(void *opaque, int arg);
80 static void radius_ip_down(void *opaque, int arg);
81 static void make_username_realm(const char *user);
82 static int radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info,
83                             struct chap_digest_type *digest,
84                             unsigned char *challenge,
85                             char *message, int message_space);
86 static void radius_choose_ip(u_int32_t *addrp);
87 static int radius_init(char *msg);
88 static int get_client_port(const char *ifname);
89 static int radius_allowed_address(u_int32_t addr);
90 static void radius_acct_interim(void *);
91 #ifdef PPP_WITH_MPPE
92 static int radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info,
93                               unsigned char *);
94 static int radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info);
95 #endif
96
97 #ifndef MAXSESSIONID
98 #define MAXSESSIONID 32
99 #endif
100
101 #ifndef MAXCLASSLEN
102 #define MAXCLASSLEN 500
103 #endif
104
105 struct radius_state {
106     int initialized;
107     int client_port;
108     int choose_ip;
109     int any_ip_addr_ok;
110     int done_chap_once;
111     u_int32_t ip_addr;
112     char user[MAXNAMELEN];
113     char config_file[MAXPATHLEN];
114     char session_id[MAXSESSIONID + 1];
115     time_t start_time;
116     int acct_interim_interval;
117     SERVER *authserver;         /* Authentication server to use */
118     SERVER *acctserver;         /* Accounting server to use */
119     int class_len;
120     char class[MAXCLASSLEN];
121     VALUE_PAIR *avp;    /* Additional (user supplied) vp's to send to server */
122 };
123
124 void (*radius_attributes_hook)(VALUE_PAIR *) = NULL;
125
126 /* The pre_auth_hook MAY set authserver and acctserver if it wants.
127    In that case, they override the values in the radiusclient.conf file */
128 void (*radius_pre_auth_hook)(char const *user,
129                              SERVER **authserver,
130                              SERVER **acctserver) = NULL;
131
132 static struct radius_state rstate;
133
134 char pppd_version[] = PPPD_VERSION;
135
136 /**********************************************************************
137 * %FUNCTION: plugin_init
138 * %ARGUMENTS:
139 *  None
140 * %RETURNS:
141 *  Nothing
142 * %DESCRIPTION:
143 *  Initializes RADIUS plugin.
144 ***********************************************************************/
145 void
146 plugin_init(void)
147 {
148     pap_check_hook = radius_secret_check;
149     pap_auth_hook = radius_pap_auth;
150
151     chap_check_hook = radius_secret_check;
152     chap_verify_hook = radius_chap_verify;
153
154     ip_choose_hook = radius_choose_ip;
155     allowed_address_hook = radius_allowed_address;
156
157     ppp_add_notify(NF_IP_UP, radius_ip_up, NULL);
158     ppp_add_notify(NF_IP_DOWN, radius_ip_down, NULL);
159
160     memset(&rstate, 0, sizeof(rstate));
161
162     strlcpy(rstate.config_file, "/etc/radiusclient/radiusclient.conf",
163             sizeof(rstate.config_file));
164
165     ppp_add_options(Options);
166
167     info("RADIUS plugin initialized.");
168 }
169
170 /**********************************************************************
171 * %FUNCTION: add_avp
172 * %ARGUMENTS:
173 *  argv -- the <attribute=value> pair to add
174 * %RETURNS:
175 *  1
176 * %DESCRIPTION:
177 *  Adds an av pair to be passed on to the RADIUS server on each request.
178 ***********************************************************************/
179 static int
180 add_avp(char **argv)
181 {
182     struct avpopt *p = malloc(sizeof(struct avpopt));
183
184     /* Append to a list of vp's for later parsing */
185     p->vpstr = strdup(*argv);
186     p->next = avpopt;
187     avpopt = p;
188
189     return 1;
190 }
191
192 /**********************************************************************
193 * %FUNCTION: radius_secret_check
194 * %ARGUMENTS:
195 *  None
196 * %RETURNS:
197 *  1 -- we are ALWAYS willing to supply a secret. :-)
198 * %DESCRIPTION:
199 * Tells pppd that we will try to authenticate the peer, and not to
200 * worry about looking in *-secrets file(s)
201 ***********************************************************************/
202 static int
203 radius_secret_check(void)
204 {
205     return 1;
206 }
207
208 /**********************************************************************
209 * %FUNCTION: radius_choose_ip
210 * %ARGUMENTS:
211 *  addrp -- where to store the IP address
212 * %RETURNS:
213 *  Nothing
214 * %DESCRIPTION:
215 *  If RADIUS server has specified an IP address, it is stored in *addrp.
216 ***********************************************************************/
217 static void
218 radius_choose_ip(u_int32_t *addrp)
219 {
220     if (rstate.choose_ip) {
221         *addrp = rstate.ip_addr;
222     }
223 }
224
225 /**********************************************************************
226 * %FUNCTION: radius_pap_auth
227 * %ARGUMENTS:
228 *  user -- user-name of peer
229 *  passwd -- password supplied by peer
230 *  msgp -- Message which will be sent in PAP response
231 *  paddrs -- set to a list of possible peer IP addresses
232 *  popts -- set to a list of additional pppd options
233 * %RETURNS:
234 *  1 if we can authenticate, -1 if we cannot.
235 * %DESCRIPTION:
236 * Performs PAP authentication using RADIUS
237 ***********************************************************************/
238 static int
239 radius_pap_auth(char *user,
240                 char *passwd,
241                 char **msgp,
242                 struct wordlist **paddrs,
243                 struct wordlist **popts)
244 {
245     VALUE_PAIR *send, *received;
246     UINT4 av_type;
247     int result;
248     static char radius_msg[BUF_LEN];
249     const char *remote_number;
250     const char *ipparam;
251
252     radius_msg[0] = 0;
253     *msgp = radius_msg;
254
255     if (radius_init(radius_msg) < 0) {
256         return 0;
257     }
258
259     /* Put user with potentially realm added in rstate.user */
260     make_username_realm(user);
261
262     if (radius_pre_auth_hook) {
263         radius_pre_auth_hook(rstate.user,
264                              &rstate.authserver,
265                              &rstate.acctserver);
266     }
267
268     send = NULL;
269     received = NULL;
270
271     /* Hack... the "port" is the ppp interface number.  Should really be
272        the tty */
273     rstate.client_port = get_client_port(portnummap ? ppp_devnam() : ppp_ifname());
274
275     av_type = PW_FRAMED;
276     rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
277
278     av_type = PW_PPP;
279     rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
280
281     rc_avpair_add(&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE);
282     rc_avpair_add(&send, PW_USER_PASSWORD, passwd, 0, VENDOR_NONE);
283     remote_number = ppp_get_remote_number();
284     ipparam = ppp_ipparam();
285     if (remote_number) {
286         rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0,
287                        VENDOR_NONE);
288     } else if (ipparam)
289         rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
290
291     /* Add user specified vp's */
292     if (rstate.avp)
293         rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
294
295     if (rstate.authserver) {
296         result = rc_auth_using_server(rstate.authserver,
297                                       rstate.client_port, send,
298                                       &received, radius_msg, NULL);
299     } else {
300         result = rc_auth(rstate.client_port, send, &received, radius_msg, NULL);
301     }
302
303     if (result == OK_RC) {
304         if (radius_setparams(received, radius_msg, NULL, NULL, NULL, NULL, 0) < 0) {
305             result = ERROR_RC;
306         }
307     }
308
309     /* free value pairs */
310     rc_avpair_free(received);
311     rc_avpair_free(send);
312
313     return (result == OK_RC) ? 1 : 0;
314 }
315
316 /**********************************************************************
317 * %FUNCTION: radius_chap_verify
318 * %ARGUMENTS:
319 *  user -- name of the peer
320 *  ourname -- name for this machine
321 *  id -- the ID byte in the challenge
322 *  digest -- points to the structure representing the digest type
323 *  challenge -- the challenge string we sent (length in first byte)
324 *  response -- the response (hash) the peer sent back (length in 1st byte)
325 *  message -- space for a message to be returned to the peer
326 *  message_space -- number of bytes available at *message.
327 * %RETURNS:
328 *  1 if the response is good, 0 if it is bad
329 * %DESCRIPTION:
330 * Performs CHAP, MS-CHAP and MS-CHAPv2 authentication using RADIUS.
331 ***********************************************************************/
332 static int
333 radius_chap_verify(char *user, char *ourname, int id,
334                    struct chap_digest_type *digest,
335                    unsigned char *challenge, unsigned char *response,
336                    char *message, int message_space)
337 {
338     VALUE_PAIR *send, *received;
339     UINT4 av_type;
340     static char radius_msg[BUF_LEN];
341     int result;
342     int challenge_len, response_len;
343     u_char cpassword[MAX_RESPONSE_LEN + 1];
344 #ifdef PPP_WITH_MPPE
345     /* Need the RADIUS secret and Request Authenticator to decode MPPE */
346     REQUEST_INFO request_info, *req_info = &request_info;
347 #else
348     REQUEST_INFO *req_info = NULL;
349 #endif
350     const char *remote_number;
351     const char *ipparam;
352
353     challenge_len = *challenge++;
354     response_len = *response++;
355
356     radius_msg[0] = 0;
357
358     if (radius_init(radius_msg) < 0) {
359         error("%s", radius_msg);
360         return 0;
361     }
362
363     /* return error for types we can't handle */
364     if ((digest->code != CHAP_MD5)
365 #ifdef PPP_WITH_CHAPMS
366         && (digest->code != CHAP_MICROSOFT)
367         && (digest->code != CHAP_MICROSOFT_V2)
368 #endif
369         ) {
370         error("RADIUS: Challenge type %u unsupported", digest->code);
371         return 0;
372     }
373
374     /* Put user with potentially realm added in rstate.user */
375     if (!rstate.done_chap_once) {
376         make_username_realm(user);
377         rstate.client_port = get_client_port (portnummap ? ppp_devnam() : ppp_ifname());
378         if (radius_pre_auth_hook) {
379             radius_pre_auth_hook(rstate.user,
380                                  &rstate.authserver,
381                                  &rstate.acctserver);
382         }
383     }
384
385     send = received = NULL;
386
387     av_type = PW_FRAMED;
388     rc_avpair_add (&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
389
390     av_type = PW_PPP;
391     rc_avpair_add (&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
392
393     rc_avpair_add (&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE);
394
395     /*
396      * add the challenge and response fields
397      */
398     switch (digest->code) {
399     case CHAP_MD5:
400         /* CHAP-Challenge and CHAP-Password */
401         if (response_len != MD5_DIGEST_LENGTH)
402             return 0;
403         cpassword[0] = id;
404         memcpy(&cpassword[1], response, MD5_DIGEST_LENGTH);
405
406         rc_avpair_add(&send, PW_CHAP_CHALLENGE,
407                       challenge, challenge_len, VENDOR_NONE);
408         rc_avpair_add(&send, PW_CHAP_PASSWORD,
409                       cpassword, MD5_DIGEST_LENGTH + 1, VENDOR_NONE);
410         break;
411
412 #ifdef PPP_WITH_CHAPMS
413     case CHAP_MICROSOFT:
414     {
415         /* MS-CHAP-Challenge and MS-CHAP-Response */
416         u_char *p = cpassword;
417
418         if (response_len != MS_CHAP_RESPONSE_LEN)
419             return 0;
420         *p++ = id;
421         /* The idiots use a different field order in RADIUS than PPP */
422         *p++ = response[MS_CHAP_USENT];
423         memcpy(p, response, MS_CHAP_LANMANRESP_LEN + MS_CHAP_NTRESP_LEN);
424
425         rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
426                       challenge, challenge_len, VENDOR_MICROSOFT);
427         rc_avpair_add(&send, PW_MS_CHAP_RESPONSE,
428                       cpassword, MS_CHAP_RESPONSE_LEN + 1, VENDOR_MICROSOFT);
429         break;
430     }
431
432     case CHAP_MICROSOFT_V2:
433     {
434         /* MS-CHAP-Challenge and MS-CHAP2-Response */
435         u_char *p = cpassword;
436
437         if (response_len != MS_CHAP2_RESPONSE_LEN)
438             return 0;
439         *p++ = id;
440         /* The idiots use a different field order in RADIUS than PPP */
441         *p++ = response[MS_CHAP2_FLAGS];
442         memcpy(p, response, (MS_CHAP2_PEER_CHAL_LEN + MS_CHAP2_RESERVED_LEN
443                              + MS_CHAP2_NTRESP_LEN));
444
445         rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
446                       challenge, challenge_len, VENDOR_MICROSOFT);
447         rc_avpair_add(&send, PW_MS_CHAP2_RESPONSE,
448                       cpassword, MS_CHAP2_RESPONSE_LEN + 1, VENDOR_MICROSOFT);
449         break;
450     }
451 #endif
452     }
453
454     remote_number = ppp_get_remote_number();
455     ipparam = ppp_ipparam();
456     if (remote_number) {
457         rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0,
458                        VENDOR_NONE);
459     } else if (ipparam)
460         rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
461
462     /* Add user specified vp's */
463     if (rstate.avp)
464         rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
465
466     /*
467      * make authentication with RADIUS server
468      */
469
470     if (rstate.authserver) {
471         result = rc_auth_using_server(rstate.authserver,
472                                       rstate.client_port, send,
473                                       &received, radius_msg, req_info);
474     } else {
475         result = rc_auth(rstate.client_port, send, &received, radius_msg,
476                          req_info);
477     }
478
479     strlcpy(message, radius_msg, message_space);
480
481     if (result == OK_RC) {
482         if (!rstate.done_chap_once) {
483             if (radius_setparams(received, radius_msg, req_info, digest,
484                                  challenge, message, message_space) < 0) {
485                 error("%s", radius_msg);
486                 result = ERROR_RC;
487             } else {
488                 rstate.done_chap_once = 1;
489             }
490         }
491     }
492
493     rc_avpair_free(received);
494     rc_avpair_free (send);
495     return (result == OK_RC);
496 }
497
498 /**********************************************************************
499 * %FUNCTION: make_username_realm
500 * %ARGUMENTS:
501 *  user -- the user given to pppd
502 * %RETURNS:
503 *  Nothing
504 * %DESCRIPTION:
505 *  Copies user into rstate.user.  If it lacks a realm (no "@domain" part),
506 * then the default realm from the radiusclient config file is added.
507 ***********************************************************************/
508 static void
509 make_username_realm(const char *user)
510 {
511     char *default_realm;
512
513     if ( user != NULL ) {
514         strlcpy(rstate.user, user, sizeof(rstate.user));
515     }  else {
516         rstate.user[0] = 0;
517     }
518
519     default_realm = rc_conf_str("default_realm");
520
521     if (!strchr(rstate.user, '@') &&
522         default_realm &&
523         (*default_realm != '\0')) {
524         strlcat(rstate.user, "@", sizeof(rstate.user));
525         strlcat(rstate.user, default_realm, sizeof(rstate.user));
526     }
527 }
528
529 /**********************************************************************
530 * %FUNCTION: radius_setparams
531 * %ARGUMENTS:
532 *  vp -- received value-pairs
533 *  msg -- buffer in which to place error message.  Holds up to BUF_LEN chars
534 * %RETURNS:
535 *  >= 0 on success; -1 on failure
536 * %DESCRIPTION:
537 *  Parses attributes sent by RADIUS server and sets them in pppd.
538 ***********************************************************************/
539 static int
540 radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info,
541                  struct chap_digest_type *digest, unsigned char *challenge,
542                  char *message, int message_space)
543 {
544     u_int32_t remote;
545     int ms_chap2_success = 0;
546 #ifdef PPP_WITH_MPPE
547     int mppe_enc_keys = 0;      /* whether or not these were received */
548     int mppe_enc_policy = 0;
549     int mppe_enc_types = 0;
550 #endif
551 #ifdef MSDNS
552     ipcp_options *wo = &ipcp_wantoptions[0];
553     ipcp_options *ao = &ipcp_allowoptions[0];
554     int got_msdns_1 = 0;
555     int got_msdns_2 = 0;
556     int got_wins_1 = 0;
557     int got_wins_2 = 0;
558 #endif
559
560     /* Send RADIUS attributes to anyone else who might be interested */
561     if (radius_attributes_hook) {
562         (*radius_attributes_hook)(vp);
563     }
564
565     /*
566      * service type (if not framed then quit),
567      * new IP address (RADIUS can define static IP for some users),
568      */
569
570     while (vp) {
571         if (vp->vendorcode == VENDOR_NONE) {
572             switch (vp->attribute) {
573             case PW_SERVICE_TYPE:
574                 /* check for service type       */
575                 /* if not FRAMED then exit      */
576                 if (vp->lvalue != PW_FRAMED) {
577                     slprintf(msg, BUF_LEN, "RADIUS: wrong service type %ld for %s",
578                              vp->lvalue, rstate.user);
579                     return -1;
580                 }
581                 break;
582
583             case PW_FRAMED_PROTOCOL:
584                 /* check for framed protocol type       */
585                 /* if not PPP then also exit            */
586                 if (vp->lvalue != PW_PPP) {
587                     slprintf(msg, BUF_LEN, "RADIUS: wrong framed protocol %ld for %s",
588                              vp->lvalue, rstate.user);
589                     return -1;
590                 }
591                 break;
592
593             case PW_SESSION_TIMEOUT:
594                 /* Session timeout */
595                 ppp_set_max_connect_time(vp->lvalue);
596                 break;
597            case PW_FILTER_ID:
598                /* packet filter, will be handled via ip-(up|down) script */
599                ppp_script_setenv("RADIUS_FILTER_ID", (char*) vp->strvalue, 1);
600                break;
601            case PW_FRAMED_ROUTE:
602                /* route, will be handled via ip-(up|down) script */
603                ppp_script_setenv("RADIUS_FRAMED_ROUTE", (char*) vp->strvalue, 1);
604                break;
605            case PW_IDLE_TIMEOUT:
606                /* idle parameter */
607                ppp_set_max_idle_time(vp->lvalue);
608                break;
609             case PW_SESSION_OCTETS_LIMIT:
610                 /* Session traffic limit */
611                 ppp_set_session_limit(vp->lvalue);
612                 break;
613             case PW_OCTETS_DIRECTION:
614                 /* Session traffic limit direction check */
615                 ppp_set_session_limit_dir(vp->lvalue);
616                 break;
617             case PW_ACCT_INTERIM_INTERVAL:
618                 /* Send accounting updates every few seconds */
619                 rstate.acct_interim_interval = vp->lvalue;
620                 /* RFC says it MUST NOT be less than 60 seconds */
621                 /* We use "0" to signify not sending updates */
622                 if (rstate.acct_interim_interval &&
623                     rstate.acct_interim_interval < 60) {
624                     rstate.acct_interim_interval = 60;
625                 }
626                 break;
627             case PW_FRAMED_IP_ADDRESS:
628                 /* seting up remote IP addresses */
629                 remote = vp->lvalue;
630                 if (remote == 0xffffffff) {
631                     /* 0xffffffff means user should be allowed to select one */
632                     rstate.any_ip_addr_ok = 1;
633                 } else if (remote != 0xfffffffe) {
634                     /* 0xfffffffe means NAS should select an ip address */
635                     remote = htonl(vp->lvalue);
636                     if (ppp_bad_ip_addr (remote)) {
637                         slprintf(msg, BUF_LEN, "RADIUS: bad remote IP address %I for %s",
638                                  remote, rstate.user);
639                         return -1;
640                     }
641                     rstate.choose_ip = 1;
642                     rstate.ip_addr = remote;
643                 }
644                 break;
645             case PW_NAS_IP_ADDRESS:
646                 wo->ouraddr = htonl(vp->lvalue);
647                 break;
648             case PW_CLASS:
649                 /* Save Class attribute to pass it in accounting request */
650                 // if (vp->lvalue <= MAXCLASSLEN) { // <- Attribute could be this big, but vp->strvalue is limited to AUTH_STRING_LEN characters
651                 if (vp->lvalue <= AUTH_STRING_LEN) {
652                     rstate.class_len=vp->lvalue;
653                     memcpy(rstate.class, vp->strvalue, rstate.class_len);
654                 } /* else too big for our buffer - ignore it */
655                 break;
656             case PW_FRAMED_MTU:
657                 ppp_set_mtu(rstate.client_port,MIN(ppp_get_mtu(rstate.client_port),vp->lvalue));
658                 break;
659             }
660
661
662         } else if (vp->vendorcode == VENDOR_MICROSOFT) {
663 #ifdef PPP_WITH_CHAPMS
664             switch (vp->attribute) {
665             case PW_MS_CHAP2_SUCCESS:
666                 if ((vp->lvalue != 43) || strncmp((char*) vp->strvalue + 1, "S=", 2)) {
667                     slprintf(msg,BUF_LEN,"RADIUS: bad MS-CHAP2-Success packet");
668                     return -1;
669                 }
670                 if (message != NULL)
671                     strlcpy(message, (char*) vp->strvalue + 1, message_space);
672                 ms_chap2_success = 1;
673                 break;
674
675 #ifdef PPP_WITH_MPPE
676             case PW_MS_CHAP_MPPE_KEYS:
677                 if (radius_setmppekeys(vp, req_info, challenge) < 0) {
678                     slprintf(msg, BUF_LEN,
679                              "RADIUS: bad MS-CHAP-MPPE-Keys attribute");
680                     return -1;
681                 }
682                 mppe_enc_keys = 1;
683                 break;
684
685             case PW_MS_MPPE_SEND_KEY:
686             case PW_MS_MPPE_RECV_KEY:
687                 if (radius_setmppekeys2(vp, req_info) < 0) {
688                     slprintf(msg, BUF_LEN,
689                              "RADIUS: bad MS-MPPE-%s-Key attribute",
690                              (vp->attribute == PW_MS_MPPE_SEND_KEY)?
691                              "Send": "Recv");
692                     return -1;
693                 }
694                 mppe_enc_keys = 1;
695                 break;
696
697             case PW_MS_MPPE_ENCRYPTION_POLICY:
698                 mppe_enc_policy = vp->lvalue;   /* save for later */
699                 break;
700
701             case PW_MS_MPPE_ENCRYPTION_TYPES:
702                 mppe_enc_types = vp->lvalue;    /* save for later */
703                 break;
704
705 #endif /* PPP_WITH_MPPE */
706 #ifdef MSDNS
707             case PW_MS_PRIMARY_DNS_SERVER:
708                 ao->dnsaddr[0] = htonl(vp->lvalue);
709                 got_msdns_1 = 1;
710                 if (!got_msdns_2)
711                     ao->dnsaddr[1] = ao->dnsaddr[0];
712                 break;
713             case PW_MS_SECONDARY_DNS_SERVER:
714                 ao->dnsaddr[1] = htonl(vp->lvalue);
715                 got_msdns_2 = 1;
716                 if (!got_msdns_1)
717                     ao->dnsaddr[0] = ao->dnsaddr[1];
718                 break;
719             case PW_MS_PRIMARY_NBNS_SERVER:
720                 ao->winsaddr[0] = htonl(vp->lvalue);
721                 got_wins_1 = 1;
722                 if (!got_wins_2)
723                     ao->winsaddr[1] = ao->winsaddr[0];
724                 break;
725             case PW_MS_SECONDARY_NBNS_SERVER:
726                 ao->winsaddr[1] = htonl(vp->lvalue);
727                 got_wins_2 = 1;
728                 if (!got_wins_1)
729                     ao->winsaddr[0] = ao->winsaddr[1];
730                 break;
731 #endif /* MSDNS */
732             }
733 #endif /* PPP_WITH_CHAPMS */
734         }
735         vp = vp->next;
736     }
737
738     /* Require a valid MS-CHAP2-SUCCESS for MS-CHAPv2 auth */
739     if (digest && (digest->code == CHAP_MICROSOFT_V2) && !ms_chap2_success)
740         return -1;
741
742 #ifdef PPP_WITH_MPPE
743     /*
744      * Require both policy and key attributes to indicate a valid key.
745      * Note that if the policy value was '0' we don't set the key!
746      */
747     if (mppe_enc_policy && mppe_enc_keys) {
748         /* Set/modify allowed encryption types. */
749         if (mppe_enc_types)
750             mppe_set_enc_types(mppe_enc_policy, mppe_enc_types);
751         return 0;
752     }
753     mppe_clear_keys();
754 #endif
755
756     return 0;
757 }
758
759 #ifdef PPP_WITH_MPPE
760 /**********************************************************************
761 * %FUNCTION: radius_setmppekeys
762 * %ARGUMENTS:
763 *  vp -- value pair holding MS-CHAP-MPPE-KEYS attribute
764 *  req_info -- radius request information used for encryption
765 * %RETURNS:
766 *  >= 0 on success; -1 on failure
767 * %DESCRIPTION:
768 *  Decrypt the "key" provided by the RADIUS server for MPPE encryption.
769 *  See RFC 2548.
770 ***********************************************************************/
771 static int
772 radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info,
773                    unsigned char *challenge)
774 {
775     int i;
776     int status = 0;
777     PPP_MD_CTX *ctx;
778     unsigned char plain[32];
779     unsigned char buf[MD5_DIGEST_LENGTH];
780     unsigned int  buflen;
781
782
783     if (vp->lvalue != 32) {
784         error("RADIUS: Incorrect attribute length (%d) for MS-CHAP-MPPE-Keys",
785               vp->lvalue);
786         return -1;
787     }
788
789     memcpy(plain, vp->strvalue, sizeof(plain));
790
791     ctx = PPP_MD_CTX_new();
792     if (ctx) {
793
794         if (PPP_DigestInit(ctx, PPP_md5())) {
795
796             if (PPP_DigestUpdate(ctx, req_info->secret, strlen(req_info->secret))) {
797
798                 if (PPP_DigestUpdate(ctx, req_info->request_vector, AUTH_VECTOR_LEN)) {
799
800                     buflen = sizeof(buf);
801                     if (PPP_DigestFinal(ctx, buf, &buflen)) {
802
803                         status = 1;
804                     }
805                 }
806             }
807         }
808         PPP_MD_CTX_free(ctx);
809     }
810
811     if (status) {
812
813         for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
814             plain[i] ^= buf[i];
815         }
816
817         status = 0;
818         ctx = PPP_MD_CTX_new();
819         if (ctx) {
820
821             if (PPP_DigestInit(ctx, PPP_md5())) {
822
823                 if (PPP_DigestUpdate(ctx, req_info->secret, strlen(req_info->secret))) {
824
825                     if (PPP_DigestUpdate(ctx, vp->strvalue, 16)) {
826
827                         buflen = MD5_DIGEST_LENGTH;
828                         if (PPP_DigestFinal(ctx, buf, &buflen)) {
829
830                             status = 1;
831                         }
832                     }
833                 }
834             }
835             PPP_MD_CTX_free(ctx);
836         }
837
838         if (status) {
839
840             for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
841                 plain[i + 16] ^= buf[i];
842             }
843
844             /*
845              * Annoying.  The "key" returned is just the NTPasswordHashHash, which
846              * the NAS (us) doesn't need; we only need the start key.  So we have
847              * to generate the start key, sigh.  NB: We do not support the LM-Key.
848              */
849             mppe_set_chapv1(challenge, &plain[8]);
850             return 0;
851         }
852     }
853
854     return -1;
855 }
856
857 /**********************************************************************
858 * %FUNCTION: radius_setmppekeys2
859 * %ARGUMENTS:
860 *  vp -- value pair holding MS-MPPE-SEND-KEY or MS-MPPE-RECV-KEY attribute
861 *  req_info -- radius request information used for encryption
862 * %RETURNS:
863 *  >= 0 on success; -1 on failure
864 * %DESCRIPTION:
865 *  Decrypt the key provided by the RADIUS server for MPPE encryption.
866 *  See RFC 2548.
867 ***********************************************************************/
868 static int
869 radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info)
870 {
871     int i;
872     int status = 0;
873     PPP_MD_CTX *ctx;
874     unsigned char *salt = vp->strvalue;
875     unsigned char *crypt = vp->strvalue + 2;
876     unsigned char plain[32];
877     unsigned char buf[MD5_DIGEST_LENGTH];
878     unsigned int  buflen;
879     char    *type = "Send";
880
881     if (vp->attribute == PW_MS_MPPE_RECV_KEY)
882         type = "Recv";
883
884     if (vp->lvalue != 34) {
885         error("RADIUS: Incorrect attribute length (%d) for MS-MPPE-%s-Key",
886               vp->lvalue, type);
887         return -1;
888     }
889
890     if ((salt[0] & 0x80) == 0) {
891         error("RADIUS: Illegal salt value for MS-MPPE-%s-Key attribute", type);
892         return -1;
893     }
894
895     memcpy(plain, crypt, 32);
896
897     ctx = PPP_MD_CTX_new();
898     if (!ctx) {
899         error("RADIUS: Error creating PPP_MD_CTX for MS-MPPE-%s-Key attribute", type);
900         return -1;
901     }
902
903     buflen = sizeof(buf);
904     if (!PPP_DigestInit(ctx, PPP_md5())) {
905         error("RADIUS: Error setting hash algorithm to MD5 for MS-MPPE-%s-Key attribute", type);
906     } else if (!PPP_DigestUpdate(ctx, req_info->secret, strlen(req_info->secret))) {
907         error("RADIUS: Error mixing in radius secret for MS-MPPE-%s-Key attribute", type);
908     } else if (!PPP_DigestUpdate(ctx, req_info->request_vector, AUTH_VECTOR_LEN)) {
909         error("RADIUS: Error mixing in request vector for MS-MPPE-%s-Key attribute", type);
910     } else if (!PPP_DigestUpdate(ctx, salt, 2)) {
911         error("RADIUS: Error mixing in salt for MS-MPPE-%s-Key attribute", type);
912     } else if (!PPP_DigestFinal(ctx, buf, &buflen)) {
913         error("RADIUS: Error finalizing key buffer for MS-MPPE-%s-Key attribute", type);
914     } else {
915         status = 1;
916     }
917
918     PPP_MD_CTX_free(ctx);
919
920     if (!status)
921         return -1;
922
923     for (i = 0; i < 16; i++) {
924         plain[i] ^= buf[i];
925     }
926
927     if (plain[0] != 16) {
928         error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute",
929                 (int) plain[0], type);
930         return -1;
931     }
932
933     status = 0;
934     ctx = PPP_MD_CTX_new();
935     if (!ctx) {
936         error("RADIUS: Error creating PPP_MD_CTX for MS-MPPE-%s-Key(2) attribute", type);
937         return -1;
938     }
939
940     buflen = sizeof(buf);
941
942     if (!PPP_DigestInit(ctx, PPP_md5())) {
943         error("RADIUS: Error setting hash algorithm to MD5 for MS-MPPE-%s-Key(2) attribute", type);
944     } else if (!PPP_DigestUpdate(ctx, req_info->secret, strlen(req_info->secret))) {
945         error("RADIUS: Error mixing in radius secret for MS-MPPE-%s-Key(2) attribute", type);
946     } else if (!PPP_DigestUpdate(ctx, crypt, 16)) {
947         error("RADIUS: Error mixing in crypt vector for MS-MPPE-%s-Key(2) attribute", type);
948     } else if (!PPP_DigestFinal(ctx, buf, &buflen)) {
949         error("RADIUS: Error finalizing key buffer for MS-MPPE-%s-Key(2) attribute", type);
950     } else {
951         status = 1;
952     }
953
954     PPP_MD_CTX_free(ctx);
955
956     if (!status)
957         return -1;
958
959     plain[16] ^= buf[0]; /* only need the first byte */
960
961     if (vp->attribute == PW_MS_MPPE_SEND_KEY) {
962         mppe_set_keys(plain + 1, NULL, 16);
963     } else {
964         mppe_set_keys(NULL, plain + 1, 16);
965     }
966     return 0;
967 }
968 #endif /* PPP_WITH_MPPE */
969
970 /**********************************************************************
971 * %FUNCTION: radius_acct_start
972 * %ARGUMENTS:
973 *  None
974 * %RETURNS:
975 *  Nothing
976 * %DESCRIPTION:
977 *  Sends a "start" accounting message to the RADIUS server.
978 ***********************************************************************/
979 static void
980 radius_acct_start(void)
981 {
982     UINT4 av_type;
983     int result;
984     VALUE_PAIR *send = NULL;
985     ipcp_options *ho = &ipcp_hisoptions[0];
986     u_int32_t hisaddr;
987     const char *remote_number;
988     const char *ipparam;
989
990     if (!rstate.initialized) {
991         return;
992     }
993
994     rstate.start_time = time(NULL);
995
996     strlcpy(rstate.session_id, rc_mksid(), MAXSESSIONID);
997
998     rc_avpair_add(&send, PW_ACCT_SESSION_ID,
999                    rstate.session_id, 0, VENDOR_NONE);
1000     rc_avpair_add(&send, PW_USER_NAME,
1001                    rstate.user, 0, VENDOR_NONE);
1002
1003     if (rstate.class_len > 0)
1004         rc_avpair_add(&send, PW_CLASS,
1005                       rstate.class, rstate.class_len, VENDOR_NONE);
1006
1007     av_type = PW_STATUS_START;
1008     rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE);
1009
1010     av_type = PW_FRAMED;
1011     rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
1012
1013     av_type = PW_PPP;
1014     rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
1015
1016     remote_number = ppp_get_remote_number();
1017     ipparam = ppp_ipparam();
1018     if (remote_number) {
1019         rc_avpair_add(&send, PW_CALLING_STATION_ID,
1020                        remote_number, 0, VENDOR_NONE);
1021     } else if (ipparam)
1022         rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
1023
1024     av_type = PW_RADIUS;
1025     rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE);
1026
1027
1028     av_type = ( ppp_using_pty() ? PW_VIRTUAL : ( ppp_sync_serial() ? PW_SYNC : PW_ASYNC ) );
1029     rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE);
1030
1031     hisaddr = ho->hisaddr;
1032     av_type = htonl(hisaddr);
1033     rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
1034
1035     /* Add user specified vp's */
1036     if (rstate.avp)
1037         rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
1038
1039     if (rstate.acctserver) {
1040         result = rc_acct_using_server(rstate.acctserver,
1041                                       rstate.client_port, send);
1042     } else {
1043         result = rc_acct(rstate.client_port, send);
1044     }
1045
1046     rc_avpair_free(send);
1047
1048     if (result != OK_RC) {
1049         /* RADIUS server could be down so make this a warning */
1050         syslog(LOG_WARNING,
1051                 "Accounting START failed for %s", rstate.user);
1052     }
1053
1054     /* Kick off periodic accounting reports */
1055     if (rstate.acct_interim_interval) {
1056         ppp_timeout(radius_acct_interim, NULL, rstate.acct_interim_interval, 0);
1057     }
1058 }
1059
1060 /**********************************************************************
1061 * %FUNCTION: radius_acct_stop
1062 * %ARGUMENTS:
1063 *  None
1064 * %RETURNS:
1065 *  Nothing
1066 * %DESCRIPTION:
1067 *  Sends a "stop" accounting message to the RADIUS server.
1068 ***********************************************************************/
1069 static void
1070 radius_acct_stop(void)
1071 {
1072     UINT4 av_type;
1073     VALUE_PAIR *send = NULL;
1074     ipcp_options *ho = &ipcp_hisoptions[0];
1075     u_int32_t hisaddr;
1076     int result;
1077     const char *remote_number;
1078     const char *ipparam;
1079     ppp_link_stats_st stats;
1080
1081     if (!rstate.initialized) {
1082         return;
1083     }
1084
1085     if (rstate.acct_interim_interval)
1086         ppp_untimeout(radius_acct_interim, NULL);
1087
1088     rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id,
1089                    0, VENDOR_NONE);
1090
1091     rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE);
1092
1093     if (rstate.class_len > 0)
1094         rc_avpair_add(&send, PW_CLASS,
1095                       rstate.class, rstate.class_len, VENDOR_NONE);
1096
1097     av_type = PW_STATUS_STOP;
1098     rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE);
1099
1100     av_type = PW_FRAMED;
1101     rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
1102
1103     av_type = PW_PPP;
1104     rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
1105
1106     av_type = PW_RADIUS;
1107     rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE);
1108
1109     if (ppp_get_link_stats(&stats)) {
1110
1111         av_type = ppp_get_link_uptime();
1112         rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE);
1113
1114         av_type = stats.bytes_out & 0xFFFFFFFF;
1115         rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE);
1116
1117         if (stats.bytes_out > 0xFFFFFFFF) {
1118             av_type = stats.bytes_out >> 32;
1119             rc_avpair_add(&send, PW_ACCT_OUTPUT_GIGAWORDS, &av_type, 0, VENDOR_NONE);
1120         }
1121
1122         av_type = stats.bytes_in & 0xFFFFFFFF;
1123         rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE);
1124
1125         if (stats.bytes_in > 0xFFFFFFFF) {
1126             av_type = stats.bytes_in >> 32;
1127             rc_avpair_add(&send, PW_ACCT_INPUT_GIGAWORDS, &av_type, 0, VENDOR_NONE);
1128         }
1129
1130         av_type = stats.pkts_out;
1131         rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE);
1132
1133         av_type = stats.pkts_in;
1134         rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE);
1135     }
1136
1137     remote_number = ppp_get_remote_number();
1138     ipparam = ppp_ipparam();
1139     if (remote_number) {
1140         rc_avpair_add(&send, PW_CALLING_STATION_ID,
1141                        remote_number, 0, VENDOR_NONE);
1142     } else if (ipparam)
1143         rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
1144
1145     av_type = ( ppp_using_pty() ? PW_VIRTUAL : ( ppp_sync_serial() ? PW_SYNC : PW_ASYNC ) );
1146     rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE);
1147
1148     av_type = PW_NAS_ERROR;
1149     switch( ppp_status() ) {
1150         case EXIT_OK:
1151             av_type = PW_USER_REQUEST;
1152             break;
1153
1154         case EXIT_USER_REQUEST:
1155             av_type = PW_ADMIN_RESET;
1156             break;
1157
1158         case EXIT_HANGUP:
1159         case EXIT_PEER_DEAD:
1160         case EXIT_CONNECT_FAILED:
1161             av_type = PW_LOST_CARRIER;
1162             break;
1163
1164         case EXIT_INIT_FAILED:
1165         case EXIT_OPEN_FAILED:
1166         case EXIT_LOCK_FAILED:
1167         case EXIT_PTYCMD_FAILED:
1168             av_type = PW_PORT_ERROR;
1169             break;
1170
1171         case EXIT_PEER_AUTH_FAILED:
1172         case EXIT_AUTH_TOPEER_FAILED:
1173         case EXIT_NEGOTIATION_FAILED:
1174         case EXIT_CNID_AUTH_FAILED:
1175             av_type = PW_SERVICE_UNAVAILABLE;
1176             break;
1177
1178         case EXIT_IDLE_TIMEOUT:
1179             av_type = PW_ACCT_IDLE_TIMEOUT;
1180             break;
1181
1182         case EXIT_CALLBACK:
1183             av_type = PW_CALLBACK;
1184             break;
1185             
1186         case EXIT_CONNECT_TIME:
1187             av_type = PW_ACCT_SESSION_TIMEOUT;
1188             break;
1189             
1190         case EXIT_TRAFFIC_LIMIT:
1191             av_type = PW_NAS_REQUEST;
1192             break;
1193
1194         default:
1195             av_type = PW_NAS_ERROR;
1196             break;
1197     }
1198     rc_avpair_add(&send, PW_ACCT_TERMINATE_CAUSE, &av_type, 0, VENDOR_NONE);
1199
1200     hisaddr = ho->hisaddr;
1201     av_type = htonl(hisaddr);
1202     rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
1203
1204     /* Add user specified vp's */
1205     if (rstate.avp)
1206         rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
1207
1208     if (rstate.acctserver) {
1209         result = rc_acct_using_server(rstate.acctserver,
1210                                       rstate.client_port, send);
1211     } else {
1212         result = rc_acct(rstate.client_port, send);
1213     }
1214
1215     if (result != OK_RC) {
1216         /* RADIUS server could be down so make this a warning */
1217         syslog(LOG_WARNING,
1218                 "Accounting STOP failed for %s", rstate.user);
1219     }
1220     rc_avpair_free(send);
1221 }
1222
1223 /**********************************************************************
1224 * %FUNCTION: radius_acct_interim
1225 * %ARGUMENTS:
1226 *  None
1227 * %RETURNS:
1228 *  Nothing
1229 * %DESCRIPTION:
1230 *  Sends an interim accounting message to the RADIUS server
1231 ***********************************************************************/
1232 static void
1233 radius_acct_interim(void *ignored)
1234 {
1235     UINT4 av_type;
1236     VALUE_PAIR *send = NULL;
1237     ipcp_options *ho = &ipcp_hisoptions[0];
1238     u_int32_t hisaddr;
1239     int result;
1240     const char *remote_number;
1241     const char *ipparam;
1242     ppp_link_stats_st stats;
1243
1244     if (!rstate.initialized) {
1245         return;
1246     }
1247
1248     rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id,
1249                    0, VENDOR_NONE);
1250
1251     rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE);
1252
1253     if (rstate.class_len > 0)
1254         rc_avpair_add(&send, PW_CLASS,
1255                       rstate.class, rstate.class_len, VENDOR_NONE);
1256
1257     av_type = PW_STATUS_ALIVE;
1258     rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE);
1259
1260     av_type = PW_FRAMED;
1261     rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
1262
1263     av_type = PW_PPP;
1264     rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
1265
1266     av_type = PW_RADIUS;
1267     rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE);
1268
1269     if (ppp_get_link_stats(&stats)) {
1270
1271         av_type = ppp_get_link_uptime();
1272         rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE);
1273
1274         av_type = stats.bytes_out & 0xFFFFFFFF;
1275         rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE);
1276
1277         if (stats.bytes_out > 0xFFFFFFFF) {
1278             av_type = stats.bytes_out >> 32;
1279             rc_avpair_add(&send, PW_ACCT_OUTPUT_GIGAWORDS, &av_type, 0, VENDOR_NONE);
1280         }
1281
1282         av_type = stats.bytes_in & 0xFFFFFFFF;
1283         rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE);
1284
1285         if (stats.bytes_in > 0xFFFFFFFF) {
1286             av_type = stats.bytes_in >> 32;
1287             rc_avpair_add(&send, PW_ACCT_INPUT_GIGAWORDS, &av_type, 0, VENDOR_NONE);
1288         }
1289
1290         av_type = stats.pkts_out;
1291         rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE);
1292
1293         av_type = stats.pkts_in;
1294         rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE);
1295     }
1296
1297     remote_number = ppp_get_remote_number();
1298     ipparam = ppp_ipparam();
1299     if (remote_number) {
1300         rc_avpair_add(&send, PW_CALLING_STATION_ID,
1301                        remote_number, 0, VENDOR_NONE);
1302     } else if (ipparam)
1303         rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
1304
1305     av_type = ( ppp_using_pty() ? PW_VIRTUAL : ( ppp_sync_serial() ? PW_SYNC : PW_ASYNC ) );
1306     rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE);
1307
1308     hisaddr = ho->hisaddr;
1309     av_type = htonl(hisaddr);
1310     rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
1311
1312     /* Add user specified vp's */
1313     if (rstate.avp)
1314         rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
1315
1316     if (rstate.acctserver) {
1317         result = rc_acct_using_server(rstate.acctserver,
1318                                       rstate.client_port, send);
1319     } else {
1320         result = rc_acct(rstate.client_port, send);
1321     }
1322
1323     if (result != OK_RC) {
1324         /* RADIUS server could be down so make this a warning */
1325         syslog(LOG_WARNING,
1326                 "Interim accounting failed for %s", rstate.user);
1327     }
1328     rc_avpair_free(send);
1329
1330     /* Schedule another one */
1331     ppp_timeout(radius_acct_interim, NULL, rstate.acct_interim_interval, 0);
1332 }
1333
1334 /**********************************************************************
1335 * %FUNCTION: radius_ip_up
1336 * %ARGUMENTS:
1337 *  opaque -- ignored
1338 *  arg -- ignored
1339 * %RETURNS:
1340 *  Nothing
1341 * %DESCRIPTION:
1342 *  Called when IPCP is up.  We'll do a start-accounting record.
1343 ***********************************************************************/
1344 static void
1345 radius_ip_up(void *opaque, int arg)
1346 {
1347     radius_acct_start();
1348 }
1349
1350 /**********************************************************************
1351 * %FUNCTION: radius_ip_down
1352 * %ARGUMENTS:
1353 *  opaque -- ignored
1354 *  arg -- ignored
1355 * %RETURNS:
1356 *  Nothing
1357 * %DESCRIPTION:
1358 *  Called when IPCP is down.  We'll do a stop-accounting record.
1359 ***********************************************************************/
1360 static void
1361 radius_ip_down(void *opaque, int arg)
1362 {
1363     radius_acct_stop();
1364 }
1365
1366 /**********************************************************************
1367 * %FUNCTION: radius_init
1368 * %ARGUMENTS:
1369 *  msg -- buffer of size BUF_LEN for error message
1370 * %RETURNS:
1371 *  negative on failure; non-negative on success
1372 * %DESCRIPTION:
1373 *  Initializes radiusclient library
1374 ***********************************************************************/
1375 static int
1376 radius_init(char *msg)
1377 {
1378     if (rstate.initialized) {
1379         return 0;
1380     }
1381
1382     if (config_file && *config_file) {
1383         strlcpy(rstate.config_file, config_file, MAXPATHLEN-1);
1384     }
1385
1386     rstate.initialized = 1;
1387
1388     if (rc_read_config(rstate.config_file) != 0) {
1389         slprintf(msg, BUF_LEN, "RADIUS: Can't read config file %s",
1390                  rstate.config_file);
1391         return -1;
1392     }
1393
1394     if (rc_read_dictionary(rc_conf_str("dictionary")) != 0) {
1395         slprintf(msg, BUF_LEN, "RADIUS: Can't read dictionary file %s",
1396                  rc_conf_str("dictionary"));
1397         return -1;
1398     }
1399
1400     if (rc_read_mapfile(rc_conf_str("mapfile")) != 0)   {
1401         slprintf(msg, BUF_LEN, "RADIUS: Can't read map file %s",
1402                  rc_conf_str("mapfile"));
1403         return -1;
1404     }
1405
1406     /* Add av pairs saved during option parsing */
1407     while (avpopt) {
1408         struct avpopt *n = avpopt->next;
1409
1410         rc_avpair_parse(avpopt->vpstr, &rstate.avp);
1411         free(avpopt->vpstr);
1412         free(avpopt);
1413         avpopt = n;
1414     }
1415     return 0;
1416 }
1417
1418 /**********************************************************************
1419 * %FUNCTION: get_client_port
1420 * %ARGUMENTS:
1421 *  ifname -- PPP interface name (e.g. "ppp7")
1422 * %RETURNS:
1423 *  The NAS port number (e.g. 7)
1424 * %DESCRIPTION:
1425 *  Extracts the port number from the interface name
1426 ***********************************************************************/
1427 static int
1428 get_client_port(const char *ifname)
1429 {
1430     int port;
1431     if (sscanf(ifname, "ppp%d", &port) == 1) {
1432         return port;
1433     }
1434     return rc_map2id(ifname);
1435 }
1436
1437 /**********************************************************************
1438 * %FUNCTION: radius_allowed_address
1439 * %ARGUMENTS:
1440 *  addr -- IP address
1441 * %RETURNS:
1442 *  1 if we're allowed to use that IP address; 0 if not; -1 if we do
1443 *  not know.
1444 ***********************************************************************/
1445 static int
1446 radius_allowed_address(u_int32_t addr)
1447 {
1448     ipcp_options *wo = &ipcp_wantoptions[0];
1449
1450     if (!rstate.choose_ip) {
1451         /* If RADIUS server said any address is OK, then fine... */
1452         if (rstate.any_ip_addr_ok) {
1453             return 1;
1454         }
1455
1456         /* Sigh... if an address was supplied for remote host in pppd
1457            options, it has to match that.  */
1458         if (wo->hisaddr != 0 && wo->hisaddr == addr) {
1459             return 1;
1460         }
1461
1462         return 0;
1463     }
1464     if (addr == rstate.ip_addr) return 1;
1465     return 0;
1466 }
1467
1468 /* Useful for other plugins */
1469 char *radius_logged_in_user(void)
1470 {
1471     return rstate.user;
1472 }