ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/trunk/usr.sbin/ppp/radius.c
Revision: 10362
Committed: Sun Jun 3 23:05:05 2018 UTC (5 years, 11 months ago) by laffer1
Content type: text/plain
File size: 40358 byte(s)
Log Message:
tag

File Contents

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

Properties

Name Value
svn:keywords MidnightBSD=%H