radius.c revision 167147
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: head/usr.sbin/ppp/radius.c 167147 2007-03-01 16:13:56Z ume $
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
100struct mschap_response {
101  u_char ident;
102  u_char flags;
103  u_char lm_response[24];
104  u_char nt_response[24];
105};
106
107struct 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
119static const char *
120radius_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
131static const char *
132radius_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
146static void
147demangle(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
226static uint8_t *
227rad_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 */
246static void
247radius_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	if ((r->ipv6prefix = rad_cvt_ipv6prefix(data, len)) == NULL) {
457	  log_Printf(LogERROR, "rad_cvt_ipv6prefix: %s\n",
458		     "Malformed attribute in response");
459	  auth_Failure(r->cx.auth);
460	  rad_close(r->cx.rad);
461	  return;
462	}
463	inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr));
464	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
465		   " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]);
466        break;
467
468      case RAD_FRAMED_IPV6_ROUTE:
469        /*
470         * We expect a string of the format ``dest[/bits] gw [metrics]''
471         * Any specified metrics are ignored.  MYADDR6 and HISADDR6 are
472         * understood for ``dest'' and ``gw'' and ``::'' is the same
473         * as ``HISADDR6''.
474         */
475
476        if ((nuke = rad_cvt_string(data, len)) == NULL) {
477          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
478          auth_Failure(r->cx.auth);
479          rad_close(r->cx.rad);
480          return;
481        }
482
483	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
484		   " IPv6 Route: %s\n", nuke);
485        bundle = r->cx.auth->physical->dl->bundle;
486	ncpaddr_setip6(&gw, &in6addr_any);
487	ncprange_set(&dest, &gw, 0);
488        argc = command_Interpret(nuke, strlen(nuke), argv);
489        if (argc < 0)
490          log_Printf(LogWARN, "radius: %s: Syntax error\n",
491                     argc == 1 ? argv[0] : "\"\"");
492        else if (argc < 2)
493          log_Printf(LogWARN, "radius: %s: Invalid route\n",
494                     argc == 1 ? argv[0] : "\"\"");
495        else if ((strcasecmp(argv[0], "default") != 0 &&
496                  !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
497                 !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
498          log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
499                     argv[0], argv[1]);
500        else {
501          addrs = 0;
502
503          if (!strncasecmp(argv[0], "HISADDR6", 8))
504            addrs = ROUTE_DSTHISADDR6;
505          else if (!strncasecmp(argv[0], "MYADDR6", 7))
506            addrs = ROUTE_DSTMYADDR6;
507
508          if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) {
509            addrs |= ROUTE_GWHISADDR6;
510            ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr);
511          } else if (strcasecmp(argv[1], "HISADDR6") == 0)
512            addrs |= ROUTE_GWHISADDR6;
513
514          route_Add(&r->ipv6routes, addrs, &dest, &gw);
515        }
516        free(nuke);
517        break;
518#endif
519
520      case RAD_VENDOR_SPECIFIC:
521        if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) {
522          log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n",
523                     rad_strerror(r->cx.rad));
524          auth_Failure(r->cx.auth);
525          rad_close(r->cx.rad);
526          return;
527        }
528
529	switch (vendor) {
530          case RAD_VENDOR_MICROSOFT:
531            switch (res) {
532#ifndef NODES
533              case RAD_MICROSOFT_MS_CHAP_ERROR:
534                free(r->errstr);
535                if (len == 0)
536                  r->errstr = NULL;
537                else {
538                  if (len < 3 || ((const char *)data)[1] != '=') {
539                    /*
540                     * Only point at the String field if we don't think the
541                     * peer has misformatted the response.
542                     */
543                    data = (const char *)data + 1;
544                    len--;
545                  } else
546                    log_Printf(LogWARN, "Warning: The MS-CHAP-Error "
547                               "attribute is mis-formatted.  Compensating\n");
548                  if ((r->errstr = rad_cvt_string((const char *)data,
549                                                  len)) == NULL) {
550                    log_Printf(LogERROR, "rad_cvt_string: %s\n",
551                               rad_strerror(r->cx.rad));
552                    auth_Failure(r->cx.auth);
553                    rad_close(r->cx.rad);
554                    return;
555                  }
556		  log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
557			     " MS-CHAP-Error \"%s\"\n", r->errstr);
558                }
559                break;
560
561              case RAD_MICROSOFT_MS_CHAP2_SUCCESS:
562                free(r->msrepstr);
563                if (len == 0)
564                  r->msrepstr = NULL;
565                else {
566                  if (len < 3 || ((const char *)data)[1] != '=') {
567                    /*
568                     * Only point at the String field if we don't think the
569                     * peer has misformatted the response.
570                     */
571                    data = (const char *)data + 1;
572                    len--;
573                  } else
574                    log_Printf(LogWARN, "Warning: The MS-CHAP2-Success "
575                               "attribute is mis-formatted.  Compensating\n");
576                  if ((r->msrepstr = rad_cvt_string((const char *)data,
577                                                    len)) == NULL) {
578                    log_Printf(LogERROR, "rad_cvt_string: %s\n",
579                               rad_strerror(r->cx.rad));
580                    auth_Failure(r->cx.auth);
581                    rad_close(r->cx.rad);
582                    return;
583                  }
584		  log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
585			     " MS-CHAP2-Success \"%s\"\n", r->msrepstr);
586                }
587                break;
588
589              case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
590                r->mppe.policy = rad_cvt_int(data);
591		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
592			   " MS-MPPE-Encryption-Policy %s\n",
593                           radius_policyname(r->mppe.policy));
594                break;
595
596              case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
597                r->mppe.types = rad_cvt_int(data);
598		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
599			   " MS-MPPE-Encryption-Types %s\n",
600                           radius_typesname(r->mppe.types));
601                break;
602
603              case RAD_MICROSOFT_MS_MPPE_RECV_KEY:
604                free(r->mppe.recvkey);
605		demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen);
606		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
607			   " MS-MPPE-Recv-Key ********\n");
608                break;
609
610              case RAD_MICROSOFT_MS_MPPE_SEND_KEY:
611		demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen);
612		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
613			   " MS-MPPE-Send-Key ********\n");
614                break;
615#endif
616
617              default:
618                log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
619                           "RADIUS attribute %d\n", res);
620                break;
621            }
622            break;
623
624          default:
625            log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n",
626                       (unsigned long)vendor, res);
627            break;
628        }
629        break;
630
631      default:
632        log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res);
633        break;
634    }
635  }
636
637  if (res == -1) {
638    log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n",
639               rad_strerror(r->cx.rad));
640    auth_Failure(r->cx.auth);
641  } else if (got == RAD_ACCESS_REJECT)
642    auth_Failure(r->cx.auth);
643  else {
644    r->valid = 1;
645    auth_Success(r->cx.auth);
646  }
647  rad_close(r->cx.rad);
648}
649
650/*
651 * We've either timed out or select()ed on the read descriptor
652 */
653static void
654radius_Continue(struct radius *r, int sel)
655{
656  struct timeval tv;
657  int got;
658
659  timer_Stop(&r->cx.timer);
660  if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) {
661    log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
662	       "Radius: Request re-sent\n");
663    r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
664    timer_Start(&r->cx.timer);
665    return;
666  }
667
668  radius_Process(r, got);
669}
670
671/*
672 * Time to call rad_continue_send_request() - timed out.
673 */
674static void
675radius_Timeout(void *v)
676{
677  radius_Continue((struct radius *)v, 0);
678}
679
680/*
681 * Time to call rad_continue_send_request() - something to read.
682 */
683static void
684radius_Read(struct fdescriptor *d, struct bundle *bundle __unused,
685	    const fd_set *fdset __unused)
686{
687  radius_Continue(descriptor2radius(d), 1);
688}
689
690/*
691 * Flush any pending transactions
692 */
693void
694radius_Flush(struct radius *r)
695{
696  struct timeval tv;
697  fd_set s;
698
699  while (r->cx.fd != -1) {
700    FD_ZERO(&s);
701    FD_SET(r->cx.fd, &s);
702    tv.tv_sec = 0;
703    tv.tv_usec = TICKUNIT;
704    select(r->cx.fd + 1, &s, NULL, NULL, &tv);
705    radius_Continue(r, 1);
706  }
707}
708
709/*
710 * Behave as a struct fdescriptor (descriptor.h)
711 */
712static int
713radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w __unused,
714		 fd_set *e __unused, int *n)
715{
716  struct radius *rad = descriptor2radius(d);
717
718  if (r && rad->cx.fd != -1) {
719    FD_SET(rad->cx.fd, r);
720    if (*n < rad->cx.fd + 1)
721      *n = rad->cx.fd + 1;
722    log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd);
723    return 1;
724  }
725
726  return 0;
727}
728
729/*
730 * Behave as a struct fdescriptor (descriptor.h)
731 */
732static int
733radius_IsSet(struct fdescriptor *d, const fd_set *fdset)
734{
735  struct radius *r = descriptor2radius(d);
736
737  return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset);
738}
739
740/*
741 * Behave as a struct fdescriptor (descriptor.h)
742 */
743static int
744radius_Write(struct fdescriptor *d __unused, struct bundle *bundle __unused,
745	     const fd_set *fdset __unused)
746{
747  /* We never want to write here ! */
748  log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n");
749  return 0;
750}
751
752/*
753 * Initialise ourselves
754 */
755void
756radius_Init(struct radius *r)
757{
758  r->desc.type = RADIUS_DESCRIPTOR;
759  r->desc.UpdateSet = radius_UpdateSet;
760  r->desc.IsSet = radius_IsSet;
761  r->desc.Read = radius_Read;
762  r->desc.Write = radius_Write;
763  r->cx.fd = -1;
764  r->cx.rad = NULL;
765  memset(&r->cx.timer, '\0', sizeof r->cx.timer);
766  r->cx.auth = NULL;
767  r->valid = 0;
768  r->vj = 0;
769  r->ip.s_addr = INADDR_ANY;
770  r->mask.s_addr = INADDR_NONE;
771  r->routes = NULL;
772  r->mtu = DEF_MTU;
773  r->msrepstr = NULL;
774  r->repstr = NULL;
775#ifndef NOINET6
776  r->ipv6prefix = NULL;
777  r->ipv6routes = NULL;
778#endif
779  r->errstr = NULL;
780  r->mppe.policy = 0;
781  r->mppe.types = 0;
782  r->mppe.recvkey = NULL;
783  r->mppe.recvkeylen = 0;
784  r->mppe.sendkey = NULL;
785  r->mppe.sendkeylen = 0;
786  *r->cfg.file = '\0';;
787  log_Printf(LogDEBUG, "Radius: radius_Init\n");
788}
789
790/*
791 * Forget everything and go back to initialised state.
792 */
793void
794radius_Destroy(struct radius *r)
795{
796  r->valid = 0;
797  log_Printf(LogDEBUG, "Radius: radius_Destroy\n");
798  timer_Stop(&r->cx.timer);
799  route_DeleteAll(&r->routes);
800#ifndef NOINET6
801  route_DeleteAll(&r->ipv6routes);
802#endif
803  free(r->filterid);
804  r->filterid = NULL;
805  free(r->msrepstr);
806  r->msrepstr = NULL;
807  free(r->repstr);
808  r->repstr = NULL;
809#ifndef NOINET6
810  free(r->ipv6prefix);
811  r->ipv6prefix = NULL;
812#endif
813  free(r->errstr);
814  r->errstr = NULL;
815  free(r->mppe.recvkey);
816  r->mppe.recvkey = NULL;
817  r->mppe.recvkeylen = 0;
818  free(r->mppe.sendkey);
819  r->mppe.sendkey = NULL;
820  r->mppe.sendkeylen = 0;
821  if (r->cx.fd != -1) {
822    r->cx.fd = -1;
823    rad_close(r->cx.rad);
824  }
825}
826
827static int
828radius_put_physical_details(struct rad_handle *rad, struct physical *p)
829{
830  int slot, type;
831
832  type = RAD_VIRTUAL;
833  if (p->handler)
834    switch (p->handler->type) {
835      case I4B_DEVICE:
836        type = RAD_ISDN_SYNC;
837        break;
838
839      case TTY_DEVICE:
840        type = RAD_ASYNC;
841        break;
842
843      case ETHER_DEVICE:
844        type = RAD_ETHERNET;
845        break;
846
847      case TCP_DEVICE:
848      case UDP_DEVICE:
849      case EXEC_DEVICE:
850      case ATM_DEVICE:
851      case NG_DEVICE:
852        type = RAD_VIRTUAL;
853        break;
854    }
855
856  if (rad_put_int(rad, RAD_NAS_PORT_TYPE, type) != 0) {
857    log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad));
858    rad_close(rad);
859    return 0;
860  }
861
862  if ((slot = physical_Slot(p)) >= 0)
863    if (rad_put_int(rad, RAD_NAS_PORT, slot) != 0) {
864      log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad));
865      rad_close(rad);
866      return 0;
867    }
868
869  return 1;
870}
871
872/*
873 * Start an authentication request to the RADIUS server.
874 */
875int
876radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
877                    const char *key, int klen, const char *nchallenge,
878                    int nclen)
879{
880  char hostname[MAXHOSTNAMELEN];
881  struct timeval tv;
882  const char *what = "questionable";	/* silence warnings! */
883  char *mac_addr;
884  int got;
885  struct hostent *hp;
886  struct in_addr hostaddr;
887#ifndef NODES
888  struct mschap_response msresp;
889  struct mschap2_response msresp2;
890  const struct MSCHAPv2_resp *keyv2;
891#endif
892
893  if (!*r->cfg.file)
894    return 0;
895
896  if (r->cx.fd != -1)
897    /*
898     * We assume that our name/key/challenge is the same as last time,
899     * and just continue to wait for the RADIUS server(s).
900     */
901    return 1;
902
903  radius_Destroy(r);
904
905  if ((r->cx.rad = rad_auth_open()) == NULL) {
906    log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
907    return 0;
908  }
909
910  if (rad_config(r->cx.rad, r->cfg.file) != 0) {
911    log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
912    rad_close(r->cx.rad);
913    return 0;
914  }
915
916  if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) {
917    log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
918    rad_close(r->cx.rad);
919    return 0;
920  }
921
922  if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 ||
923      rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
924      rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) {
925    log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
926    rad_close(r->cx.rad);
927    return 0;
928  }
929
930  switch (authp->physical->link.lcp.want_auth) {
931  case PROTO_PAP:
932    /* We're talking PAP */
933    if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) {
934      log_Printf(LogERROR, "PAP: rad_put_string: %s\n",
935                 rad_strerror(r->cx.rad));
936      rad_close(r->cx.rad);
937      return 0;
938    }
939    what = "PAP";
940    break;
941
942  case PROTO_CHAP:
943    switch (authp->physical->link.lcp.want_authtype) {
944    case 0x5:
945      if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 ||
946          rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) {
947        log_Printf(LogERROR, "CHAP: rad_put_string: %s\n",
948                   rad_strerror(r->cx.rad));
949        rad_close(r->cx.rad);
950        return 0;
951      }
952      what = "CHAP";
953      break;
954
955#ifndef NODES
956    case 0x80:
957      if (klen != 50) {
958        log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen);
959        rad_close(r->cx.rad);
960        return 0;
961      }
962
963      rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
964                          RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
965      msresp.ident = *key;
966      msresp.flags = 0x01;
967      memcpy(msresp.lm_response, key + 1, 24);
968      memcpy(msresp.nt_response, key + 25, 24);
969      rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
970                          RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp,
971                          sizeof msresp);
972      what = "MSCHAP";
973      break;
974
975    case 0x81:
976      if (klen != sizeof(*keyv2) + 1) {
977        log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen);
978        rad_close(r->cx.rad);
979        return 0;
980      }
981
982      keyv2 = (const struct MSCHAPv2_resp *)(key + 1);
983      rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
984                          RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
985      msresp2.ident = *key;
986      msresp2.flags = keyv2->Flags;
987      memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response);
988      memset(msresp2.reserved, '\0', sizeof msresp2.reserved);
989      memcpy(msresp2.pchallenge, keyv2->PeerChallenge,
990             sizeof msresp2.pchallenge);
991      rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
992                          RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2,
993                          sizeof msresp2);
994      what = "MSCHAPv2";
995      break;
996#endif
997    default:
998      log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n",
999                 authp->physical->link.lcp.want_authtype);
1000      rad_close(r->cx.rad);
1001      return 0;
1002    }
1003  }
1004
1005  if (gethostname(hostname, sizeof hostname) != 0)
1006    log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
1007  else {
1008    if (Enabled(authp->physical->dl->bundle, OPT_NAS_IP_ADDRESS) &&
1009        (hp = gethostbyname(hostname)) != NULL) {
1010      hostaddr.s_addr = *(u_long *)hp->h_addr;
1011      if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
1012        log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
1013                   rad_strerror(r->cx.rad));
1014        rad_close(r->cx.rad);
1015        return 0;
1016      }
1017    }
1018    if (Enabled(authp->physical->dl->bundle, OPT_NAS_IDENTIFIER) &&
1019        rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
1020      log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
1021                 rad_strerror(r->cx.rad));
1022      rad_close(r->cx.rad);
1023      return 0;
1024    }
1025  }
1026
1027  if ((mac_addr = getenv("HISMACADDR")) != NULL &&
1028      rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) {
1029    log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1030    rad_close(r->cx.rad);
1031    return 0;
1032  }
1033
1034  radius_put_physical_details(r->cx.rad, authp->physical);
1035
1036  log_Printf(LogRADIUS, "Radius(auth): %s data sent for %s\n", what, name);
1037
1038  r->cx.auth = authp;
1039  if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
1040    radius_Process(r, got);
1041  else {
1042    log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
1043	       "Radius: Request sent\n");
1044    log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
1045    r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
1046    r->cx.timer.func = radius_Timeout;
1047    r->cx.timer.name = "radius auth";
1048    r->cx.timer.arg = r;
1049    timer_Start(&r->cx.timer);
1050  }
1051
1052  return 1;
1053}
1054
1055/* Fetch IP, netmask from IPCP */
1056void
1057radius_Account_Set_Ip(struct radacct *ac, struct in_addr *peer_ip,
1058		      struct in_addr *netmask)
1059{
1060  ac->proto = PROTO_IPCP;
1061  memcpy(&ac->peer.ip.addr, peer_ip, sizeof(ac->peer.ip.addr));
1062  memcpy(&ac->peer.ip.mask, netmask, sizeof(ac->peer.ip.mask));
1063}
1064
1065#ifndef NOINET6
1066/* Fetch interface-id from IPV6CP */
1067void
1068radius_Account_Set_Ipv6(struct radacct *ac, u_char *ifid)
1069{
1070  ac->proto = PROTO_IPV6CP;
1071  memcpy(&ac->peer.ipv6.ifid, ifid, sizeof(ac->peer.ipv6.ifid));
1072}
1073#endif
1074
1075/*
1076 * Send an accounting request to the RADIUS server
1077 */
1078void
1079radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl,
1080               int acct_type, struct pppThroughput *stats)
1081{
1082  struct timeval tv;
1083  int got;
1084  char hostname[MAXHOSTNAMELEN];
1085  char *mac_addr;
1086  struct hostent *hp;
1087  struct in_addr hostaddr;
1088
1089  if (!*r->cfg.file)
1090    return;
1091
1092  if (r->cx.fd != -1)
1093    /*
1094     * We assume that our name/key/challenge is the same as last time,
1095     * and just continue to wait for the RADIUS server(s).
1096     */
1097    return;
1098
1099  timer_Stop(&r->cx.timer);
1100
1101  if ((r->cx.rad = rad_acct_open()) == NULL) {
1102    log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
1103    return;
1104  }
1105
1106  if (rad_config(r->cx.rad, r->cfg.file) != 0) {
1107    log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
1108    rad_close(r->cx.rad);
1109    return;
1110  }
1111
1112  if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) {
1113    log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
1114    rad_close(r->cx.rad);
1115    return;
1116  }
1117
1118  /* Grab some accounting data and initialize structure */
1119  if (acct_type == RAD_START) {
1120    ac->rad_parent = r;
1121    /* Fetch username from datalink */
1122    strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name);
1123    ac->user_name[AUTHLEN-1] = '\0';
1124
1125    ac->authentic = 2;		/* Assume RADIUS verified auth data */
1126
1127    /* Generate a session ID */
1128    snprintf(ac->session_id, sizeof ac->session_id, "%s%ld-%s%lu",
1129             dl->bundle->cfg.auth.name, (long)getpid(),
1130             dl->peer.authname, (unsigned long)stats->uptime);
1131
1132    /* And grab our MP socket name */
1133    snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s",
1134             dl->bundle->ncp.mp.active ?
1135             dl->bundle->ncp.mp.server.socket.sun_path : "");
1136  };
1137
1138  if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 ||
1139      rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
1140      rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) {
1141    log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1142    rad_close(r->cx.rad);
1143    return;
1144  }
1145  switch (ac->proto) {
1146  case PROTO_IPCP:
1147    if (rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS,
1148		     ac->peer.ip.addr) != 0 ||
1149	rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK,
1150		     ac->peer.ip.mask) != 0) {
1151      log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1152      rad_close(r->cx.rad);
1153      return;
1154    }
1155    break;
1156#ifndef NOINET6
1157  case PROTO_IPV6CP:
1158    if (rad_put_attr(r->cx.rad, RAD_FRAMED_INTERFACE_ID, ac->peer.ipv6.ifid,
1159		     sizeof(ac->peer.ipv6.ifid)) != 0) {
1160      log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad));
1161      rad_close(r->cx.rad);
1162      return;
1163    }
1164    if (r->ipv6prefix) {
1165      /*
1166       * Since PPP doesn't delegate an IPv6 prefix to a peer,
1167       * Framed-IPv6-Prefix may be not used, actually.
1168       */
1169      if (rad_put_attr(r->cx.rad, RAD_FRAMED_IPV6_PREFIX, r->ipv6prefix,
1170		       sizeof(struct in6_addr) + 2) != 0) {
1171	log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad));
1172	rad_close(r->cx.rad);
1173	return;
1174      }
1175    }
1176    break;
1177#endif
1178  default:
1179    /* We don't log any protocol specific information */
1180    break;
1181  }
1182
1183  if ((mac_addr = getenv("HISMACADDR")) != NULL &&
1184      rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) {
1185    log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1186    rad_close(r->cx.rad);
1187    return;
1188  }
1189
1190  if (gethostname(hostname, sizeof hostname) != 0)
1191    log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
1192  else {
1193    if (Enabled(dl->bundle, OPT_NAS_IP_ADDRESS) &&
1194        (hp = gethostbyname(hostname)) != NULL) {
1195      hostaddr.s_addr = *(u_long *)hp->h_addr;
1196      if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
1197        log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
1198                   rad_strerror(r->cx.rad));
1199        rad_close(r->cx.rad);
1200        return;
1201      }
1202    }
1203    if (Enabled(dl->bundle, OPT_NAS_IDENTIFIER) &&
1204        rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
1205      log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
1206                 rad_strerror(r->cx.rad));
1207      rad_close(r->cx.rad);
1208      return;
1209    }
1210  }
1211
1212  radius_put_physical_details(r->cx.rad, dl->physical);
1213
1214  if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 ||
1215      rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 ||
1216      rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID,
1217                     ac->multi_session_id) != 0 ||
1218      rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) {
1219/* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */
1220    log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1221    rad_close(r->cx.rad);
1222    return;
1223  }
1224
1225  if (acct_type == RAD_STOP || acct_type == RAD_ALIVE)
1226    /* Show some statistics */
1227    if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn % UINT32_MAX) != 0 ||
1228        rad_put_int(r->cx.rad, RAD_ACCT_INPUT_GIGAWORDS, stats->OctetsIn / UINT32_MAX) != 0 ||
1229        rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 ||
1230        rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut % UINT32_MAX) != 0 ||
1231        rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_GIGAWORDS, stats->OctetsOut / UINT32_MAX) != 0 ||
1232        rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut)
1233        != 0 ||
1234        rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats))
1235        != 0) {
1236      log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1237      rad_close(r->cx.rad);
1238      return;
1239    }
1240
1241  if (log_IsKept(LogPHASE) || log_IsKept(LogRADIUS)) {
1242    const char *what;
1243    int level;
1244
1245    switch (acct_type) {
1246    case RAD_START:
1247      what = "START";
1248      level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
1249      break;
1250    case RAD_STOP:
1251      what = "STOP";
1252      level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
1253      break;
1254    case RAD_ALIVE:
1255      what = "ALIVE";
1256      level = LogRADIUS;
1257      break;
1258    default:
1259      what = "<unknown>";
1260      level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
1261      break;
1262    }
1263    log_Printf(level, "Radius(acct): %s data sent\n", what);
1264  }
1265
1266  r->cx.auth = NULL;			/* Not valid for accounting requests */
1267  if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
1268    radius_Process(r, got);
1269  else {
1270    log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
1271    r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
1272    r->cx.timer.func = radius_Timeout;
1273    r->cx.timer.name = "radius acct";
1274    r->cx.timer.arg = r;
1275    timer_Start(&r->cx.timer);
1276  }
1277}
1278
1279/*
1280 * How do things look at the moment ?
1281 */
1282void
1283radius_Show(struct radius *r, struct prompt *p)
1284{
1285  prompt_Printf(p, " Radius config:     %s",
1286                *r->cfg.file ? r->cfg.file : "none");
1287  if (r->valid) {
1288    prompt_Printf(p, "\n                IP: %s\n", inet_ntoa(r->ip));
1289    prompt_Printf(p, "           Netmask: %s\n", inet_ntoa(r->mask));
1290    prompt_Printf(p, "               MTU: %lu\n", r->mtu);
1291    prompt_Printf(p, "                VJ: %sabled\n", r->vj ? "en" : "dis");
1292    prompt_Printf(p, "           Message: %s\n", r->repstr ? r->repstr : "");
1293    prompt_Printf(p, "   MPPE Enc Policy: %s\n",
1294                  radius_policyname(r->mppe.policy));
1295    prompt_Printf(p, "    MPPE Enc Types: %s\n",
1296                  radius_typesname(r->mppe.types));
1297    prompt_Printf(p, "     MPPE Recv Key: %seceived\n",
1298                  r->mppe.recvkey ? "R" : "Not r");
1299    prompt_Printf(p, "     MPPE Send Key: %seceived\n",
1300                  r->mppe.sendkey ? "R" : "Not r");
1301    prompt_Printf(p, " MS-CHAP2-Response: %s\n",
1302                  r->msrepstr ? r->msrepstr : "");
1303    prompt_Printf(p, "     Error Message: %s\n", r->errstr ? r->errstr : "");
1304    if (r->routes)
1305      route_ShowSticky(p, r->routes, "            Routes", 16);
1306#ifndef NOINET6
1307    if (r->ipv6routes)
1308      route_ShowSticky(p, r->ipv6routes, "            IPv6 Routes", 16);
1309#endif
1310  } else
1311    prompt_Printf(p, " (not authenticated)\n");
1312}
1313
1314static void
1315radius_alive(void *v)
1316{
1317  struct bundle *bundle = (struct bundle *)v;
1318
1319  timer_Stop(&bundle->radius.alive.timer);
1320  bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS;
1321  if (bundle->radius.alive.timer.load) {
1322    radius_Account(&bundle->radius, &bundle->radacct,
1323                   bundle->links, RAD_ALIVE, &bundle->ncp.ipcp.throughput);
1324    timer_Start(&bundle->radius.alive.timer);
1325  }
1326}
1327
1328void
1329radius_StartTimer(struct bundle *bundle)
1330{
1331  if (bundle->radius.cfg.file && bundle->radius.alive.interval) {
1332    bundle->radius.alive.timer.func = radius_alive;
1333    bundle->radius.alive.timer.name = "radius alive";
1334    bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS;
1335    bundle->radius.alive.timer.arg = bundle;
1336    radius_alive(bundle);
1337  }
1338}
1339
1340void
1341radius_StopTimer(struct radius *r)
1342{
1343  timer_Stop(&r->alive.timer);
1344}
1345