]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/ppp/radius.c
This commit was generated by cvs2svn to compensate for changes in r146768,
[FreeBSD/FreeBSD.git] / usr.sbin / ppp / radius.c
1 /*
2  * Copyright 1999 Internet Business Solutions Ltd., Switzerland
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  *
28  */
29
30 #include <stdint.h>
31 #include <sys/param.h>
32
33 #include <sys/select.h>
34 #include <sys/socket.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/in.h>
37 #include <netinet/ip.h>
38 #include <arpa/inet.h>
39 #include <sys/un.h>
40 #include <net/route.h>
41
42 #ifdef LOCALRAD
43 #include "radlib.h"
44 #include "radlib_vs.h"
45 #else
46 #include <radlib.h>
47 #include <radlib_vs.h>
48 #endif
49
50 #include <errno.h>
51 #ifndef NODES
52 #include <md5.h>
53 #endif
54 #include <stdarg.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <sys/time.h>
59 #include <termios.h>
60 #include <unistd.h>
61 #include <netdb.h>
62
63 #include "layer.h"
64 #include "defs.h"
65 #include "log.h"
66 #include "descriptor.h"
67 #include "prompt.h"
68 #include "timer.h"
69 #include "fsm.h"
70 #include "iplist.h"
71 #include "slcompress.h"
72 #include "throughput.h"
73 #include "lqr.h"
74 #include "hdlc.h"
75 #include "mbuf.h"
76 #include "ncpaddr.h"
77 #include "ip.h"
78 #include "ipcp.h"
79 #include "ipv6cp.h"
80 #include "route.h"
81 #include "command.h"
82 #include "filter.h"
83 #include "lcp.h"
84 #include "ccp.h"
85 #include "link.h"
86 #include "mp.h"
87 #include "radius.h"
88 #include "auth.h"
89 #include "async.h"
90 #include "physical.h"
91 #include "chat.h"
92 #include "cbcp.h"
93 #include "chap.h"
94 #include "datalink.h"
95 #include "ncp.h"
96 #include "bundle.h"
97 #include "proto.h"
98
99 #ifndef NODES
100 struct mschap_response {
101   u_char ident;
102   u_char flags;
103   u_char lm_response[24];
104   u_char nt_response[24];
105 };
106
107 struct mschap2_response {
108   u_char ident;
109   u_char flags;
110   u_char pchallenge[16];
111   u_char reserved[8];
112   u_char response[24];
113 };
114
115 #define AUTH_LEN        16
116 #define SALT_LEN        2
117 #endif
118
119 static const char *
120 radius_policyname(int policy)
121 {
122   switch(policy) {
123   case MPPE_POLICY_ALLOWED:
124     return "Allowed";
125   case MPPE_POLICY_REQUIRED:
126     return "Required";
127   }
128   return NumStr(policy, NULL, 0);
129 }
130
131 static const char *
132 radius_typesname(int types)
133 {
134   switch(types) {
135   case MPPE_TYPE_40BIT:
136     return "40 bit";
137   case MPPE_TYPE_128BIT:
138     return "128 bit";
139   case MPPE_TYPE_40BIT|MPPE_TYPE_128BIT:
140     return "40 or 128 bit";
141   }
142   return NumStr(types, NULL, 0);
143 }
144
145 #ifndef NODES
146 static void
147 demangle(struct radius *r, const void *mangled, size_t mlen,
148          char **buf, size_t *len)
149 {
150   char R[AUTH_LEN];             /* variable names as per rfc2548 */
151   const char *S;
152   u_char b[16];
153   const u_char *A, *C;
154   MD5_CTX Context;
155   int Slen, i, Clen, Ppos;
156   u_char *P;
157
158   if (mlen % 16 != SALT_LEN) {
159     log_Printf(LogWARN, "Cannot interpret mangled data of length %ld\n",
160                (u_long)mlen);
161     *buf = NULL;
162     *len = 0;
163     return;
164   }
165
166   /* We need the RADIUS Request-Authenticator */
167   if (rad_request_authenticator(r->cx.rad, R, sizeof R) != AUTH_LEN) {
168     log_Printf(LogWARN, "Cannot obtain the RADIUS request authenticator\n");
169     *buf = NULL;
170     *len = 0;
171     return;
172   }
173
174   A = (const u_char *)mangled;                  /* Salt comes first */
175   C = (const u_char *)mangled + SALT_LEN;       /* Then the ciphertext */
176   Clen = mlen - SALT_LEN;
177   S = rad_server_secret(r->cx.rad);             /* We need the RADIUS secret */
178   Slen = strlen(S);
179   P = alloca(Clen);                             /* We derive our plaintext */
180
181   MD5Init(&Context);
182   MD5Update(&Context, S, Slen);
183   MD5Update(&Context, R, AUTH_LEN);
184   MD5Update(&Context, A, SALT_LEN);
185   MD5Final(b, &Context);
186   Ppos = 0;
187
188   while (Clen) {
189     Clen -= 16;
190
191     for (i = 0; i < 16; i++)
192       P[Ppos++] = C[i] ^ b[i];
193
194     if (Clen) {
195       MD5Init(&Context);
196       MD5Update(&Context, S, Slen);
197       MD5Update(&Context, C, 16);
198       MD5Final(b, &Context);
199     }
200
201     C += 16;
202   }
203
204   /*
205    * The resulting plain text consists of a one-byte length, the text and
206    * maybe some padding.
207    */
208   *len = *P;
209   if (*len > mlen - 1) {
210     log_Printf(LogWARN, "Mangled data seems to be garbage\n");
211     *buf = NULL;
212     *len = 0;
213     return;
214   }
215
216   if ((*buf = malloc(*len)) == NULL) {
217     log_Printf(LogWARN, "demangle: Out of memory (%lu bytes)\n", (u_long)*len);
218     *len = 0;
219   } else
220     memcpy(*buf, P + 1, *len);
221 }
222 #endif
223
224 /* XXX: This should go into librarius. */
225 #ifndef NOINET6
226 static uint8_t *
227 rad_cvt_ipv6prefix(const void *data, size_t len)
228 {
229         const size_t ipv6len = sizeof(struct in6_addr) + 2;
230         uint8_t *s;
231
232         if (len > ipv6len)
233                 return NULL;
234         s = malloc(ipv6len);
235         if (s != NULL) {
236                 memset(s, 0, ipv6len);
237                 memcpy(s, data, len);
238         }
239         return s;
240 }
241 #endif
242
243 /*
244  * rad_continue_send_request() has given us `got' (non-zero).  Deal with it.
245  */
246 static void
247 radius_Process(struct radius *r, int got)
248 {
249   char *argv[MAXARGS], *nuke;
250   struct bundle *bundle;
251   int argc, addrs, res, width;
252   size_t len;
253   struct ncprange dest;
254   struct ncpaddr gw;
255   const void *data;
256   const char *stype;
257   u_int32_t ipaddr, vendor;
258   struct in_addr ip;
259 #ifndef NOINET6
260   uint8_t ipv6addr[INET6_ADDRSTRLEN];
261   struct in6_addr ip6;
262 #endif
263
264   r->cx.fd = -1;                /* Stop select()ing */
265   stype = r->cx.auth ? "auth" : "acct";
266
267   switch (got) {
268     case RAD_ACCESS_ACCEPT:
269       log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
270                  "Radius(%s): ACCEPT received\n", stype);
271       if (!r->cx.auth) {
272         rad_close(r->cx.rad);
273         return;
274       }
275       break;
276
277     case RAD_ACCESS_REJECT:
278       log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
279                  "Radius(%s): REJECT received\n", stype);
280       if (!r->cx.auth) {
281         rad_close(r->cx.rad);
282         return;
283       }
284       break;
285
286     case RAD_ACCESS_CHALLENGE:
287       /* we can't deal with this (for now) ! */
288       log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
289                  "Radius: CHALLENGE received (can't handle yet)\n");
290       if (r->cx.auth)
291         auth_Failure(r->cx.auth);
292       rad_close(r->cx.rad);
293       return;
294
295     case RAD_ACCOUNTING_RESPONSE:
296       /*
297        * It's probably not ideal to log this at PHASE level as we'll see
298        * too much stuff going to the log when ``set rad_alive'' is used.
299        * So we differ from older behaviour (ppp version 3.1 and before)
300        * and just log accounting responses to LogRADIUS.
301        */
302       log_Printf(LogRADIUS, "Radius(%s): Accounting response received\n",
303                  stype);
304       if (r->cx.auth)
305         auth_Failure(r->cx.auth);               /* unexpected !!! */
306
307       /* No further processing for accounting requests, please */
308       rad_close(r->cx.rad);
309       return;
310
311     case -1:
312       log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
313                  "radius(%s): %s\n", stype, rad_strerror(r->cx.rad));
314       if (r->cx.auth)
315         auth_Failure(r->cx.auth);
316       rad_close(r->cx.rad);
317       return;
318
319     default:
320       log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype,
321                  got, rad_strerror(r->cx.rad));
322       if (r->cx.auth)
323         auth_Failure(r->cx.auth);
324       rad_close(r->cx.rad);
325       return;
326   }
327
328   /* Let's see what we've got in our reply */
329   r->ip.s_addr = r->mask.s_addr = INADDR_NONE;
330   r->mtu = 0;
331   r->vj = 0;
332   while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) {
333     switch (res) {
334       case RAD_FRAMED_IP_ADDRESS:
335         r->ip = rad_cvt_addr(data);
336         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
337                    " IP %s\n", inet_ntoa(r->ip));
338         break;
339
340       case RAD_FILTER_ID:
341         free(r->filterid);
342         if ((r->filterid = rad_cvt_string(data, len)) == NULL) {
343           log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
344           auth_Failure(r->cx.auth);
345           rad_close(r->cx.rad);
346           return;
347         }
348         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
349                    " Filter \"%s\"\n", r->filterid);
350         break;
351
352       case RAD_SESSION_TIMEOUT:
353         r->sessiontime = rad_cvt_int(data);
354         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
355                    " Session-Timeout %lu\n", r->sessiontime);
356         break;
357
358       case RAD_FRAMED_IP_NETMASK:
359         r->mask = rad_cvt_addr(data);
360         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
361                    " Netmask %s\n", inet_ntoa(r->mask));
362         break;
363
364       case RAD_FRAMED_MTU:
365         r->mtu = rad_cvt_int(data);
366         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
367                    " MTU %lu\n", r->mtu);
368         break;
369
370       case RAD_FRAMED_ROUTING:
371         /* Disabled for now - should we automatically set up some filters ? */
372         /* rad_cvt_int(data); */
373         /* bit 1 = Send routing packets */
374         /* bit 2 = Receive routing packets */
375         break;
376
377       case RAD_FRAMED_COMPRESSION:
378         r->vj = rad_cvt_int(data) == 1 ? 1 : 0;
379         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
380                    " VJ %sabled\n", r->vj ? "en" : "dis");
381         break;
382
383       case RAD_FRAMED_ROUTE:
384         /*
385          * We expect a string of the format ``dest[/bits] gw [metrics]''
386          * Any specified metrics are ignored.  MYADDR and HISADDR are
387          * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same
388          * as ``HISADDR''.
389          */
390
391         if ((nuke = rad_cvt_string(data, len)) == NULL) {
392           log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
393           auth_Failure(r->cx.auth);
394           rad_close(r->cx.rad);
395           return;
396         }
397
398         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
399                    " Route: %s\n", nuke);
400         bundle = r->cx.auth->physical->dl->bundle;
401         ip.s_addr = INADDR_ANY;
402         ncpaddr_setip4(&gw, ip);
403         ncprange_setip4host(&dest, ip);
404         argc = command_Interpret(nuke, strlen(nuke), argv);
405         if (argc < 0)
406           log_Printf(LogWARN, "radius: %s: Syntax error\n",
407                      argc == 1 ? argv[0] : "\"\"");
408         else if (argc < 2)
409           log_Printf(LogWARN, "radius: %s: Invalid route\n",
410                      argc == 1 ? argv[0] : "\"\"");
411         else if ((strcasecmp(argv[0], "default") != 0 &&
412                   !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
413                  !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
414           log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
415                      argv[0], argv[1]);
416         else {
417           ncprange_getwidth(&dest, &width);
418           if (width == 32 && strchr(argv[0], '/') == NULL) {
419             /* No mask specified - use the natural mask */
420             ncprange_getip4addr(&dest, &ip);
421             ncprange_setip4mask(&dest, addr2mask(ip));
422           }
423           addrs = 0;
424
425           if (!strncasecmp(argv[0], "HISADDR", 7))
426             addrs = ROUTE_DSTHISADDR;
427           else if (!strncasecmp(argv[0], "MYADDR", 6))
428             addrs = ROUTE_DSTMYADDR;
429
430           if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) {
431             addrs |= ROUTE_GWHISADDR;
432             ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip);
433           } else if (strcasecmp(argv[1], "HISADDR") == 0)
434             addrs |= ROUTE_GWHISADDR;
435
436           route_Add(&r->routes, addrs, &dest, &gw);
437         }
438         free(nuke);
439         break;
440
441       case RAD_REPLY_MESSAGE:
442         free(r->repstr);
443         if ((r->repstr = rad_cvt_string(data, len)) == NULL) {
444           log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
445           auth_Failure(r->cx.auth);
446           rad_close(r->cx.rad);
447           return;
448         }
449         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
450                    " Reply-Message \"%s\"\n", r->repstr);
451         break;
452
453 #ifndef NOINET6
454       case RAD_FRAMED_IPV6_PREFIX:
455         free(r->ipv6prefix);
456         r->ipv6prefix = rad_cvt_ipv6prefix(data, len);
457         inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr));
458         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
459                    " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]);
460         break;
461
462       case RAD_FRAMED_IPV6_ROUTE:
463         /*
464          * We expect a string of the format ``dest[/bits] gw [metrics]''
465          * Any specified metrics are ignored.  MYADDR6 and HISADDR6 are
466          * understood for ``dest'' and ``gw'' and ``::'' is the same
467          * as ``HISADDR6''.
468          */
469
470         if ((nuke = rad_cvt_string(data, len)) == NULL) {
471           log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
472           auth_Failure(r->cx.auth);
473           rad_close(r->cx.rad);
474           return;
475         }
476
477         log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
478                    " IPv6 Route: %s\n", nuke);
479         bundle = r->cx.auth->physical->dl->bundle;
480         ncpaddr_setip6(&gw, &in6addr_any);
481         ncprange_set(&dest, &gw, 0);
482         argc = command_Interpret(nuke, strlen(nuke), argv);
483         if (argc < 0)
484           log_Printf(LogWARN, "radius: %s: Syntax error\n",
485                      argc == 1 ? argv[0] : "\"\"");
486         else if (argc < 2)
487           log_Printf(LogWARN, "radius: %s: Invalid route\n",
488                      argc == 1 ? argv[0] : "\"\"");
489         else if ((strcasecmp(argv[0], "default") != 0 &&
490                   !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
491                  !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
492           log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
493                      argv[0], argv[1]);
494         else {
495           addrs = 0;
496
497           if (!strncasecmp(argv[0], "HISADDR6", 8))
498             addrs = ROUTE_DSTHISADDR6;
499           else if (!strncasecmp(argv[0], "MYADDR6", 7))
500             addrs = ROUTE_DSTMYADDR6;
501
502           if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) {
503             addrs |= ROUTE_GWHISADDR6;
504             ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr);
505           } else if (strcasecmp(argv[1], "HISADDR6") == 0)
506             addrs |= ROUTE_GWHISADDR6;
507
508           route_Add(&r->ipv6routes, addrs, &dest, &gw);
509         }
510         free(nuke);
511         break;
512 #endif
513
514       case RAD_VENDOR_SPECIFIC:
515         if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) {
516           log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n",
517                      rad_strerror(r->cx.rad));
518           auth_Failure(r->cx.auth);
519           rad_close(r->cx.rad);
520           return;
521         }
522
523         switch (vendor) {
524           case RAD_VENDOR_MICROSOFT:
525             switch (res) {
526 #ifndef NODES
527               case RAD_MICROSOFT_MS_CHAP_ERROR:
528                 free(r->errstr);
529                 if (len == 0)
530                   r->errstr = NULL;
531                 else {
532                   if (len < 3 || ((const char *)data)[1] != '=') {
533                     /*
534                      * Only point at the String field if we don't think the
535                      * peer has misformatted the response.
536                      */
537                     data = (const char *)data + 1;
538                     len--;
539                   } else
540                     log_Printf(LogWARN, "Warning: The MS-CHAP-Error "
541                                "attribute is mis-formatted.  Compensating\n");
542                   if ((r->errstr = rad_cvt_string((const char *)data,
543                                                   len)) == NULL) {
544                     log_Printf(LogERROR, "rad_cvt_string: %s\n",
545                                rad_strerror(r->cx.rad));
546                     auth_Failure(r->cx.auth);
547                     rad_close(r->cx.rad);
548                     return;
549                   }
550                   log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
551                              " MS-CHAP-Error \"%s\"\n", r->errstr);
552                 }
553                 break;
554
555               case RAD_MICROSOFT_MS_CHAP2_SUCCESS:
556                 free(r->msrepstr);
557                 if (len == 0)
558                   r->msrepstr = NULL;
559                 else {
560                   if (len < 3 || ((const char *)data)[1] != '=') {
561                     /*
562                      * Only point at the String field if we don't think the
563                      * peer has misformatted the response.
564                      */
565                     data = (const char *)data + 1;
566                     len--;
567                   } else
568                     log_Printf(LogWARN, "Warning: The MS-CHAP2-Success "
569                                "attribute is mis-formatted.  Compensating\n");
570                   if ((r->msrepstr = rad_cvt_string((const char *)data,
571                                                     len)) == NULL) {
572                     log_Printf(LogERROR, "rad_cvt_string: %s\n",
573                                rad_strerror(r->cx.rad));
574                     auth_Failure(r->cx.auth);
575                     rad_close(r->cx.rad);
576                     return;
577                   }
578                   log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
579                              " MS-CHAP2-Success \"%s\"\n", r->msrepstr);
580                 }
581                 break;
582
583               case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
584                 r->mppe.policy = rad_cvt_int(data);
585                 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
586                            " MS-MPPE-Encryption-Policy %s\n",
587                            radius_policyname(r->mppe.policy));
588                 break;
589
590               case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
591                 r->mppe.types = rad_cvt_int(data);
592                 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
593                            " MS-MPPE-Encryption-Types %s\n",
594                            radius_typesname(r->mppe.types));
595                 break;
596
597               case RAD_MICROSOFT_MS_MPPE_RECV_KEY:
598                 free(r->mppe.recvkey);
599                 demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen);
600                 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
601                            " MS-MPPE-Recv-Key ********\n");
602                 break;
603
604               case RAD_MICROSOFT_MS_MPPE_SEND_KEY:
605                 demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen);
606                 log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
607                            " MS-MPPE-Send-Key ********\n");
608                 break;
609 #endif
610
611               default:
612                 log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
613                            "RADIUS attribute %d\n", res);
614                 break;
615             }
616             break;
617
618           default:
619             log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n",
620                        (unsigned long)vendor, res);
621             break;
622         }
623         break;
624
625       default:
626         log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res);
627         break;
628     }
629   }
630
631   if (res == -1) {
632     log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n",
633                rad_strerror(r->cx.rad));
634     auth_Failure(r->cx.auth);
635   } else if (got == RAD_ACCESS_REJECT)
636     auth_Failure(r->cx.auth);
637   else {
638     r->valid = 1;
639     auth_Success(r->cx.auth);
640   }
641   rad_close(r->cx.rad);
642 }
643
644 /*
645  * We've either timed out or select()ed on the read descriptor
646  */
647 static void
648 radius_Continue(struct radius *r, int sel)
649 {
650   struct timeval tv;
651   int got;
652
653   timer_Stop(&r->cx.timer);
654   if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) {
655     log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
656                "Radius: Request re-sent\n");
657     r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
658     timer_Start(&r->cx.timer);
659     return;
660   }
661
662   radius_Process(r, got);
663 }
664
665 /*
666  * Time to call rad_continue_send_request() - timed out.
667  */
668 static void
669 radius_Timeout(void *v)
670 {
671   radius_Continue((struct radius *)v, 0);
672 }
673
674 /*
675  * Time to call rad_continue_send_request() - something to read.
676  */
677 static void
678 radius_Read(struct fdescriptor *d, struct bundle *bundle __unused,
679             const fd_set *fdset __unused)
680 {
681   radius_Continue(descriptor2radius(d), 1);
682 }
683
684 /*
685  * Flush any pending transactions
686  */
687 void
688 radius_Flush(struct radius *r)
689 {
690   struct timeval tv;
691   fd_set s;
692
693   while (r->cx.fd != -1) {
694     FD_ZERO(&s);
695     FD_SET(r->cx.fd, &s);
696     tv.tv_sec = 0;
697     tv.tv_usec = TICKUNIT;
698     select(r->cx.fd + 1, &s, NULL, NULL, &tv);
699     radius_Continue(r, 1);
700   }
701 }
702
703 /*
704  * Behave as a struct fdescriptor (descriptor.h)
705  */
706 static int
707 radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w __unused,
708                  fd_set *e __unused, int *n)
709 {
710   struct radius *rad = descriptor2radius(d);
711
712   if (r && rad->cx.fd != -1) {
713     FD_SET(rad->cx.fd, r);
714     if (*n < rad->cx.fd + 1)
715       *n = rad->cx.fd + 1;
716     log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd);
717     return 1;
718   }
719
720   return 0;
721 }
722
723 /*
724  * Behave as a struct fdescriptor (descriptor.h)
725  */
726 static int
727 radius_IsSet(struct fdescriptor *d, const fd_set *fdset)
728 {
729   struct radius *r = descriptor2radius(d);
730
731   return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset);
732 }
733
734 /*
735  * Behave as a struct fdescriptor (descriptor.h)
736  */
737 static int
738 radius_Write(struct fdescriptor *d __unused, struct bundle *bundle __unused,
739              const fd_set *fdset __unused)
740 {
741   /* We never want to write here ! */
742   log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n");
743   return 0;
744 }
745
746 /*
747  * Initialise ourselves
748  */
749 void
750 radius_Init(struct radius *r)
751 {
752   r->desc.type = RADIUS_DESCRIPTOR;
753   r->desc.UpdateSet = radius_UpdateSet;
754   r->desc.IsSet = radius_IsSet;
755   r->desc.Read = radius_Read;
756   r->desc.Write = radius_Write;
757   r->cx.fd = -1;
758   r->cx.rad = NULL;
759   memset(&r->cx.timer, '\0', sizeof r->cx.timer);
760   r->cx.auth = NULL;
761   r->valid = 0;
762   r->vj = 0;
763   r->ip.s_addr = INADDR_ANY;
764   r->mask.s_addr = INADDR_NONE;
765   r->routes = NULL;
766   r->mtu = DEF_MTU;
767   r->msrepstr = NULL;
768   r->repstr = NULL;
769 #ifndef NOINET6
770   r->ipv6prefix = NULL;
771   r->ipv6routes = NULL;
772 #endif
773   r->errstr = NULL;
774   r->mppe.policy = 0;
775   r->mppe.types = 0;
776   r->mppe.recvkey = NULL;
777   r->mppe.recvkeylen = 0;
778   r->mppe.sendkey = NULL;
779   r->mppe.sendkeylen = 0;
780   *r->cfg.file = '\0';;
781   log_Printf(LogDEBUG, "Radius: radius_Init\n");
782 }
783
784 /*
785  * Forget everything and go back to initialised state.
786  */
787 void
788 radius_Destroy(struct radius *r)
789 {
790   r->valid = 0;
791   log_Printf(LogDEBUG, "Radius: radius_Destroy\n");
792   timer_Stop(&r->cx.timer);
793   route_DeleteAll(&r->routes);
794 #ifndef NOINET6
795   route_DeleteAll(&r->ipv6routes);
796 #endif
797   free(r->filterid);
798   r->filterid = NULL;
799   free(r->msrepstr);
800   r->msrepstr = NULL;
801   free(r->repstr);
802   r->repstr = NULL;
803 #ifndef NOINET6
804   free(r->ipv6prefix);
805   r->ipv6prefix = NULL;
806 #endif
807   free(r->errstr);
808   r->errstr = NULL;
809   free(r->mppe.recvkey);
810   r->mppe.recvkey = NULL;
811   r->mppe.recvkeylen = 0;
812   free(r->mppe.sendkey);
813   r->mppe.sendkey = NULL;
814   r->mppe.sendkeylen = 0;
815   if (r->cx.fd != -1) {
816     r->cx.fd = -1;
817     rad_close(r->cx.rad);
818   }
819 }
820
821 static int
822 radius_put_physical_details(struct rad_handle *rad, struct physical *p)
823 {
824   int slot, type;
825
826   type = RAD_VIRTUAL;
827   if (p->handler)
828     switch (p->handler->type) {
829       case I4B_DEVICE:
830         type = RAD_ISDN_SYNC;
831         break;
832
833       case TTY_DEVICE:
834         type = RAD_ASYNC;
835         break;
836
837       case ETHER_DEVICE:
838         type = RAD_ETHERNET;
839         break;
840
841       case TCP_DEVICE:
842       case UDP_DEVICE:
843       case EXEC_DEVICE:
844       case ATM_DEVICE:
845       case NG_DEVICE:
846         type = RAD_VIRTUAL;
847         break;
848     }
849
850   if (rad_put_int(rad, RAD_NAS_PORT_TYPE, type) != 0) {
851     log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad));
852     rad_close(rad);
853     return 0;
854   }
855
856   if ((slot = physical_Slot(p)) >= 0)
857     if (rad_put_int(rad, RAD_NAS_PORT, slot) != 0) {
858       log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad));
859       rad_close(rad);
860       return 0;
861     }
862
863   return 1;
864 }
865
866 /*
867  * Start an authentication request to the RADIUS server.
868  */
869 int
870 radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
871                     const char *key, int klen, const char *nchallenge,
872                     int nclen)
873 {
874   char hostname[MAXHOSTNAMELEN];
875   struct timeval tv;
876   const char *what = "questionable";    /* silence warnings! */
877   char *mac_addr;
878   int got;
879   struct hostent *hp;
880   struct in_addr hostaddr;
881 #ifndef NODES
882   struct mschap_response msresp;
883   struct mschap2_response msresp2;
884   const struct MSCHAPv2_resp *keyv2;
885 #endif
886
887   if (!*r->cfg.file)
888     return 0;
889
890   if (r->cx.fd != -1)
891     /*
892      * We assume that our name/key/challenge is the same as last time,
893      * and just continue to wait for the RADIUS server(s).
894      */
895     return 1;
896
897   radius_Destroy(r);
898
899   if ((r->cx.rad = rad_auth_open()) == NULL) {
900     log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
901     return 0;
902   }
903
904   if (rad_config(r->cx.rad, r->cfg.file) != 0) {
905     log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
906     rad_close(r->cx.rad);
907     return 0;
908   }
909
910   if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) {
911     log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
912     rad_close(r->cx.rad);
913     return 0;
914   }
915
916   if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 ||
917       rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
918       rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) {
919     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
920     rad_close(r->cx.rad);
921     return 0;
922   }
923
924   switch (authp->physical->link.lcp.want_auth) {
925   case PROTO_PAP:
926     /* We're talking PAP */
927     if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) {
928       log_Printf(LogERROR, "PAP: rad_put_string: %s\n",
929                  rad_strerror(r->cx.rad));
930       rad_close(r->cx.rad);
931       return 0;
932     }
933     what = "PAP";
934     break;
935
936   case PROTO_CHAP:
937     switch (authp->physical->link.lcp.want_authtype) {
938     case 0x5:
939       if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 ||
940           rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) {
941         log_Printf(LogERROR, "CHAP: rad_put_string: %s\n",
942                    rad_strerror(r->cx.rad));
943         rad_close(r->cx.rad);
944         return 0;
945       }
946       what = "CHAP";
947       break;
948
949 #ifndef NODES
950     case 0x80:
951       if (klen != 50) {
952         log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen);
953         rad_close(r->cx.rad);
954         return 0;
955       }
956
957       rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
958                           RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
959       msresp.ident = *key;
960       msresp.flags = 0x01;
961       memcpy(msresp.lm_response, key + 1, 24);
962       memcpy(msresp.nt_response, key + 25, 24);
963       rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
964                           RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp,
965                           sizeof msresp);
966       what = "MSCHAP";
967       break;
968
969     case 0x81:
970       if (klen != sizeof(*keyv2) + 1) {
971         log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen);
972         rad_close(r->cx.rad);
973         return 0;
974       }
975
976       keyv2 = (const struct MSCHAPv2_resp *)(key + 1);
977       rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
978                           RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
979       msresp2.ident = *key;
980       msresp2.flags = keyv2->Flags;
981       memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response);
982       memset(msresp2.reserved, '\0', sizeof msresp2.reserved);
983       memcpy(msresp2.pchallenge, keyv2->PeerChallenge,
984              sizeof msresp2.pchallenge);
985       rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
986                           RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2,
987                           sizeof msresp2);
988       what = "MSCHAPv2";
989       break;
990 #endif
991     default:
992       log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n",
993                  authp->physical->link.lcp.want_authtype);
994       rad_close(r->cx.rad);
995       return 0;
996     }
997   }
998
999   if (gethostname(hostname, sizeof hostname) != 0)
1000     log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
1001   else {
1002     if (Enabled(authp->physical->dl->bundle, OPT_NAS_IP_ADDRESS) &&
1003         (hp = gethostbyname(hostname)) != NULL) {
1004       hostaddr.s_addr = *(u_long *)hp->h_addr;
1005       if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
1006         log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
1007                    rad_strerror(r->cx.rad));
1008         rad_close(r->cx.rad);
1009         return 0;
1010       }
1011     }
1012     if (Enabled(authp->physical->dl->bundle, OPT_NAS_IDENTIFIER) &&
1013         rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
1014       log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
1015                  rad_strerror(r->cx.rad));
1016       rad_close(r->cx.rad);
1017       return 0;
1018     }
1019   }
1020
1021   if ((mac_addr = getenv("HISMACADDR")) != NULL &&
1022       rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) {
1023     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1024     rad_close(r->cx.rad);
1025     return 0;
1026   }
1027
1028   radius_put_physical_details(r->cx.rad, authp->physical);
1029
1030   log_Printf(LogRADIUS, "Radius(auth): %s data sent for %s\n", what, name);
1031
1032   r->cx.auth = authp;
1033   if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
1034     radius_Process(r, got);
1035   else {
1036     log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
1037                "Radius: Request sent\n");
1038     log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
1039     r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
1040     r->cx.timer.func = radius_Timeout;
1041     r->cx.timer.name = "radius auth";
1042     r->cx.timer.arg = r;
1043     timer_Start(&r->cx.timer);
1044   }
1045
1046   return 1;
1047 }
1048
1049 /* Fetch IP, netmask from IPCP */
1050 void
1051 radius_Account_Set_Ip(struct radacct *ac, struct in_addr *peer_ip,
1052                       struct in_addr *netmask)
1053 {
1054   ac->proto = PROTO_IPCP;
1055   memcpy(&ac->peer.ip.addr, peer_ip, sizeof(ac->peer.ip.addr));
1056   memcpy(&ac->peer.ip.mask, netmask, sizeof(ac->peer.ip.mask));
1057 }
1058
1059 #ifndef NOINET6
1060 /* Fetch interface-id from IPV6CP */
1061 void
1062 radius_Account_Set_Ipv6(struct radacct *ac, u_char *ifid)
1063 {
1064   ac->proto = PROTO_IPV6CP;
1065   memcpy(&ac->peer.ipv6.ifid, ifid, sizeof(ac->peer.ipv6.ifid));
1066 }
1067 #endif
1068
1069 /*
1070  * Send an accounting request to the RADIUS server
1071  */
1072 void
1073 radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl,
1074                int acct_type, struct pppThroughput *stats)
1075 {
1076   struct timeval tv;
1077   int got;
1078   char hostname[MAXHOSTNAMELEN];
1079   char *mac_addr;
1080   struct hostent *hp;
1081   struct in_addr hostaddr;
1082
1083   if (!*r->cfg.file)
1084     return;
1085
1086   if (r->cx.fd != -1)
1087     /*
1088      * We assume that our name/key/challenge is the same as last time,
1089      * and just continue to wait for the RADIUS server(s).
1090      */
1091     return;
1092
1093   timer_Stop(&r->cx.timer);
1094
1095   if ((r->cx.rad = rad_acct_open()) == NULL) {
1096     log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
1097     return;
1098   }
1099
1100   if (rad_config(r->cx.rad, r->cfg.file) != 0) {
1101     log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
1102     rad_close(r->cx.rad);
1103     return;
1104   }
1105
1106   if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) {
1107     log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
1108     rad_close(r->cx.rad);
1109     return;
1110   }
1111
1112   /* Grab some accounting data and initialize structure */
1113   if (acct_type == RAD_START) {
1114     ac->rad_parent = r;
1115     /* Fetch username from datalink */
1116     strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name);
1117     ac->user_name[AUTHLEN-1] = '\0';
1118
1119     ac->authentic = 2;          /* Assume RADIUS verified auth data */
1120
1121     /* Generate a session ID */
1122     snprintf(ac->session_id, sizeof ac->session_id, "%s%ld-%s%lu",
1123              dl->bundle->cfg.auth.name, (long)getpid(),
1124              dl->peer.authname, (unsigned long)stats->uptime);
1125
1126     /* And grab our MP socket name */
1127     snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s",
1128              dl->bundle->ncp.mp.active ?
1129              dl->bundle->ncp.mp.server.socket.sun_path : "");
1130   };
1131
1132   if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 ||
1133       rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
1134       rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) {
1135     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1136     rad_close(r->cx.rad);
1137     return;
1138   }
1139   switch (ac->proto) {
1140   case PROTO_IPCP:
1141     if (rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS,
1142                      ac->peer.ip.addr) != 0 ||
1143         rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK,
1144                      ac->peer.ip.mask) != 0) {
1145       log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1146       rad_close(r->cx.rad);
1147       return;
1148     }
1149     break;
1150 #ifndef NOINET6
1151   case PROTO_IPV6CP:
1152     if (rad_put_attr(r->cx.rad, RAD_FRAMED_INTERFACE_ID, ac->peer.ipv6.ifid,
1153                      sizeof(ac->peer.ipv6.ifid)) != 0) {
1154       log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad));
1155       rad_close(r->cx.rad);
1156       return;
1157     }
1158     if (r->ipv6prefix) {
1159       /*
1160        * Since PPP doesn't delegate an IPv6 prefix to a peer,
1161        * Framed-IPv6-Prefix may be not used, actually.
1162        */
1163       if (rad_put_attr(r->cx.rad, RAD_FRAMED_IPV6_PREFIX, r->ipv6prefix,
1164                        sizeof(struct in6_addr) + 2) != 0) {
1165         log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad));
1166         rad_close(r->cx.rad);
1167         return;
1168       }
1169     }
1170     break;
1171 #endif
1172   default:
1173     /* We don't log any protocol specific information */
1174     break;
1175   }
1176
1177   if ((mac_addr = getenv("HISMACADDR")) != NULL &&
1178       rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) {
1179     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1180     rad_close(r->cx.rad);
1181     return;
1182   }
1183
1184   if (gethostname(hostname, sizeof hostname) != 0)
1185     log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
1186   else {
1187     if (Enabled(dl->bundle, OPT_NAS_IP_ADDRESS) &&
1188         (hp = gethostbyname(hostname)) != NULL) {
1189       hostaddr.s_addr = *(u_long *)hp->h_addr;
1190       if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
1191         log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
1192                    rad_strerror(r->cx.rad));
1193         rad_close(r->cx.rad);
1194         return;
1195       }
1196     }
1197     if (Enabled(dl->bundle, OPT_NAS_IDENTIFIER) &&
1198         rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
1199       log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
1200                  rad_strerror(r->cx.rad));
1201       rad_close(r->cx.rad);
1202       return;
1203     }
1204   }
1205
1206   radius_put_physical_details(r->cx.rad, dl->physical);
1207
1208   if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 ||
1209       rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 ||
1210       rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID,
1211                      ac->multi_session_id) != 0 ||
1212       rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) {
1213 /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */
1214     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1215     rad_close(r->cx.rad);
1216     return;
1217   }
1218
1219   if (acct_type == RAD_STOP || acct_type == RAD_ALIVE)
1220     /* Show some statistics */
1221     if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn % UINT32_MAX) != 0 ||
1222         rad_put_int(r->cx.rad, RAD_ACCT_INPUT_GIGAWORDS, stats->OctetsIn / UINT32_MAX) != 0 ||
1223         rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 ||
1224         rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut % UINT32_MAX) != 0 ||
1225         rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_GIGAWORDS, stats->OctetsOut / UINT32_MAX) != 0 ||
1226         rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut)
1227         != 0 ||
1228         rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats))
1229         != 0) {
1230       log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1231       rad_close(r->cx.rad);
1232       return;
1233     }
1234
1235   if (log_IsKept(LogPHASE) || log_IsKept(LogRADIUS)) {
1236     const char *what;
1237     int level;
1238
1239     switch (acct_type) {
1240     case RAD_START:
1241       what = "START";
1242       level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
1243       break;
1244     case RAD_STOP:
1245       what = "STOP";
1246       level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
1247       break;
1248     case RAD_ALIVE:
1249       what = "ALIVE";
1250       level = LogRADIUS;
1251       break;
1252     default:
1253       what = "<unknown>";
1254       level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
1255       break;
1256     }
1257     log_Printf(level, "Radius(acct): %s data sent\n", what);
1258   }
1259   
1260   r->cx.auth = NULL;                    /* Not valid for accounting requests */
1261   if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
1262     radius_Process(r, got);
1263   else {
1264     log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
1265     r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
1266     r->cx.timer.func = radius_Timeout;
1267     r->cx.timer.name = "radius acct";
1268     r->cx.timer.arg = r;
1269     timer_Start(&r->cx.timer);
1270   }
1271 }
1272
1273 /*
1274  * How do things look at the moment ?
1275  */
1276 void
1277 radius_Show(struct radius *r, struct prompt *p)
1278 {
1279   prompt_Printf(p, " Radius config:     %s",
1280                 *r->cfg.file ? r->cfg.file : "none");
1281   if (r->valid) {
1282     prompt_Printf(p, "\n                IP: %s\n", inet_ntoa(r->ip));
1283     prompt_Printf(p, "           Netmask: %s\n", inet_ntoa(r->mask));
1284     prompt_Printf(p, "               MTU: %lu\n", r->mtu);
1285     prompt_Printf(p, "                VJ: %sabled\n", r->vj ? "en" : "dis");
1286     prompt_Printf(p, "           Message: %s\n", r->repstr ? r->repstr : "");
1287     prompt_Printf(p, "   MPPE Enc Policy: %s\n",
1288                   radius_policyname(r->mppe.policy));
1289     prompt_Printf(p, "    MPPE Enc Types: %s\n",
1290                   radius_typesname(r->mppe.types));
1291     prompt_Printf(p, "     MPPE Recv Key: %seceived\n",
1292                   r->mppe.recvkey ? "R" : "Not r");
1293     prompt_Printf(p, "     MPPE Send Key: %seceived\n",
1294                   r->mppe.sendkey ? "R" : "Not r");
1295     prompt_Printf(p, " MS-CHAP2-Response: %s\n",
1296                   r->msrepstr ? r->msrepstr : "");
1297     prompt_Printf(p, "     Error Message: %s\n", r->errstr ? r->errstr : "");
1298     if (r->routes)
1299       route_ShowSticky(p, r->routes, "            Routes", 16);
1300 #ifndef NOINET6
1301     if (r->ipv6routes)
1302       route_ShowSticky(p, r->ipv6routes, "            IPv6 Routes", 16);
1303 #endif
1304   } else
1305     prompt_Printf(p, " (not authenticated)\n");
1306 }
1307
1308 static void
1309 radius_alive(void *v)
1310 {
1311   struct bundle *bundle = (struct bundle *)v;
1312
1313   timer_Stop(&bundle->radius.alive.timer);
1314   bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS;
1315   if (bundle->radius.alive.timer.load) {
1316     radius_Account(&bundle->radius, &bundle->radacct,
1317                    bundle->links, RAD_ALIVE, &bundle->ncp.ipcp.throughput);
1318     timer_Start(&bundle->radius.alive.timer);
1319   }
1320 }
1321
1322 void
1323 radius_StartTimer(struct bundle *bundle)
1324 {
1325   if (bundle->radius.cfg.file && bundle->radius.alive.interval) {
1326     bundle->radius.alive.timer.func = radius_alive;
1327     bundle->radius.alive.timer.name = "radius alive";
1328     bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS;
1329     bundle->radius.alive.timer.arg = bundle;
1330     radius_alive(bundle);
1331   }
1332 }
1333
1334 void
1335 radius_StopTimer(struct radius *r)
1336 {
1337   timer_Stop(&r->alive.timer);
1338 }