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 * $OpenBSD: radius.c,v 1.26 2005/07/17 19:13:25 brad Exp $
27 *
28 */
29
30 #include <sys/param.h>
31
32 #include <sys/socket.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <arpa/inet.h>
37 #include <sys/un.h>
38 #include <net/route.h>
39
40 #ifdef LOCALRAD
41 #include "radlib.h"
42 #include "radlib_vs.h"
43 #else
44 #include <radlib.h>
45 #include <radlib_vs.h>
46 #endif
47
48 #include <errno.h>
49 #ifndef NODES
50 #include <md5.h>
51 #endif
52 #include <stdarg.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <sys/time.h>
57 #include <termios.h>
58 #include <unistd.h>
59 #include <netdb.h>
60
61 #include "layer.h"
62 #include "defs.h"
63 #include "log.h"
64 #include "descriptor.h"
65 #include "prompt.h"
66 #include "timer.h"
67 #include "fsm.h"
68 #include "iplist.h"
69 #include "slcompress.h"
70 #include "throughput.h"
71 #include "lqr.h"
72 #include "hdlc.h"
73 #include "mbuf.h"
74 #include "ncpaddr.h"
75 #include "ip.h"
76 #include "ipcp.h"
77 #include "ipv6cp.h"
78 #include "route.h"
79 #include "command.h"
80 #include "filter.h"
81 #include "lcp.h"
82 #include "ccp.h"
83 #include "link.h"
84 #include "mp.h"
85 #include "radius.h"
86 #include "auth.h"
87 #include "async.h"
88 #include "physical.h"
89 #include "chat.h"
90 #include "cbcp.h"
91 #include "chap.h"
92 #include "datalink.h"
93 #include "ncp.h"
94 #include "bundle.h"
95 #include "proto.h"
96
97 #ifndef NODES
98 struct mschap_response {
99 u_char ident;
100 u_char flags;
101 u_char lm_response[24];
102 u_char nt_response[24];
103 };
104
105 struct mschap2_response {
106 u_char ident;
107 u_char flags;
108 u_char pchallenge[16];
109 u_char reserved[8];
110 u_char response[24];
111 };
112
113 #define AUTH_LEN 16
114 #define SALT_LEN 2
115 #endif
116
117 static const char *
radius_policyname(int policy)118 radius_policyname(int policy)
119 {
120 switch(policy) {
121 case MPPE_POLICY_ALLOWED:
122 return "Allowed";
123 case MPPE_POLICY_REQUIRED:
124 return "Required";
125 }
126 return NumStr(policy, NULL, 0);
127 }
128
129 static const char *
radius_typesname(int types)130 radius_typesname(int types)
131 {
132 switch(types) {
133 case MPPE_TYPE_40BIT:
134 return "40 bit";
135 case MPPE_TYPE_128BIT:
136 return "128 bit";
137 case MPPE_TYPE_40BIT|MPPE_TYPE_128BIT:
138 return "40 or 128 bit";
139 }
140 return NumStr(types, NULL, 0);
141 }
142
143 #ifndef NODES
144 static void
demangle(struct radius * r,const void * mangled,size_t mlen,char ** buf,size_t * len)145 demangle(struct radius *r, const void *mangled, size_t mlen,
146 char **buf, size_t *len)
147 {
148 char R[AUTH_LEN]; /* variable names as per rfc2548 */
149 const char *S;
150 u_char b[16];
151 const u_char *A, *C;
152 MD5_CTX Context;
153 int Slen, i, Clen, Ppos;
154 u_char *P;
155
156 if (mlen % 16 != SALT_LEN) {
157 log_Printf(LogWARN, "Cannot interpret mangled data of length %ld\n",
158 (u_long)mlen);
159 *buf = NULL;
160 *len = 0;
161 return;
162 }
163
164 /* We need the RADIUS Request-Authenticator */
165 if (rad_request_authenticator(r->cx.rad, R, sizeof R) != AUTH_LEN) {
166 log_Printf(LogWARN, "Cannot obtain the RADIUS request authenticator\n");
167 *buf = NULL;
168 *len = 0;
169 return;
170 }
171
172 A = (const u_char *)mangled; /* Salt comes first */
173 C = (const u_char *)mangled + SALT_LEN; /* Then the ciphertext */
174 Clen = mlen - SALT_LEN;
175 S = rad_server_secret(r->cx.rad); /* We need the RADIUS secret */
176 Slen = strlen(S);
177 P = alloca(Clen); /* We derive our plaintext */
178
179 MD5Init(&Context);
180 MD5Update(&Context, S, Slen);
181 MD5Update(&Context, R, AUTH_LEN);
182 MD5Update(&Context, A, SALT_LEN);
183 MD5Final(b, &Context);
184 Ppos = 0;
185
186 while (Clen) {
187 Clen -= 16;
188
189 for (i = 0; i < 16; i++)
190 P[Ppos++] = C[i] ^ b[i];
191
192 if (Clen) {
193 MD5Init(&Context);
194 MD5Update(&Context, S, Slen);
195 MD5Update(&Context, C, 16);
196 MD5Final(b, &Context);
197 }
198
199 C += 16;
200 }
201
202 /*
203 * The resulting plain text consists of a one-byte length, the text and
204 * maybe some padding.
205 */
206 *len = *P;
207 if (*len > mlen - 1) {
208 log_Printf(LogWARN, "Mangled data seems to be garbage\n");
209 *buf = NULL;
210 *len = 0;
211 return;
212 }
213
214 if ((*buf = malloc(*len)) == NULL) {
215 log_Printf(LogWARN, "demangle: Out of memory (%lu bytes)\n", (u_long)*len);
216 *len = 0;
217 } else
218 memcpy(*buf, P + 1, *len);
219 }
220 #endif
221
222 /*
223 * rad_continue_send_request() has given us `got' (non-zero). Deal with it.
224 */
225 static void
radius_Process(struct radius * r,int got)226 radius_Process(struct radius *r, int got)
227 {
228 char *argv[MAXARGS], *nuke;
229 struct bundle *bundle;
230 int argc, addrs, res, width;
231 size_t len;
232 struct ncprange dest;
233 struct ncpaddr gw;
234 const void *data;
235 const char *stype;
236 u_int32_t ipaddr, vendor;
237 struct in_addr ip;
238
239 r->cx.fd = -1; /* Stop select()ing */
240 stype = r->cx.auth ? "auth" : "acct";
241
242 switch (got) {
243 case RAD_ACCESS_ACCEPT:
244 log_Printf(LogPHASE, "Radius(%s): ACCEPT received\n", stype);
245 if (!r->cx.auth) {
246 rad_close(r->cx.rad);
247 return;
248 }
249 break;
250
251 case RAD_ACCESS_REJECT:
252 log_Printf(LogPHASE, "Radius(%s): REJECT received\n", stype);
253 if (!r->cx.auth) {
254 rad_close(r->cx.rad);
255 return;
256 }
257 break;
258
259 case RAD_ACCESS_CHALLENGE:
260 /* we can't deal with this (for now) ! */
261 log_Printf(LogPHASE, "Radius: CHALLENGE received (can't handle yet)\n");
262 if (r->cx.auth)
263 auth_Failure(r->cx.auth);
264 rad_close(r->cx.rad);
265 return;
266
267 case RAD_ACCOUNTING_RESPONSE:
268 log_Printf(LogPHASE, "Radius(%s): Accounting response received\n", stype);
269 if (r->cx.auth)
270 auth_Failure(r->cx.auth); /* unexpected !!! */
271
272 /* No further processing for accounting requests, please */
273 rad_close(r->cx.rad);
274 return;
275
276 case -1:
277 log_Printf(LogPHASE, "radius(%s): %s\n", stype, rad_strerror(r->cx.rad));
278 if (r->cx.auth)
279 auth_Failure(r->cx.auth);
280 rad_close(r->cx.rad);
281 return;
282
283 default:
284 log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype,
285 got, rad_strerror(r->cx.rad));
286 if (r->cx.auth)
287 auth_Failure(r->cx.auth);
288 rad_close(r->cx.rad);
289 return;
290 }
291
292 /* Let's see what we've got in our reply */
293 r->ip.s_addr = r->mask.s_addr = INADDR_NONE;
294 r->mtu = 0;
295 r->vj = 0;
296 while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) {
297 switch (res) {
298 case RAD_FRAMED_IP_ADDRESS:
299 r->ip = rad_cvt_addr(data);
300 log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip));
301 break;
302
303 case RAD_FILTER_ID:
304 free(r->filterid);
305 if ((r->filterid = rad_cvt_string(data, len)) == NULL) {
306 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
307 auth_Failure(r->cx.auth);
308 rad_close(r->cx.rad);
309 return;
310 }
311 log_Printf(LogPHASE, " Filter \"%s\"\n", r->filterid);
312 break;
313
314 case RAD_SESSION_TIMEOUT:
315 r->sessiontime = rad_cvt_int(data);
316 log_Printf(LogPHASE, " Session-Timeout %lu\n", r->sessiontime);
317 break;
318
319 case RAD_FRAMED_IP_NETMASK:
320 r->mask = rad_cvt_addr(data);
321 log_Printf(LogPHASE, " Netmask %s\n", inet_ntoa(r->mask));
322 break;
323
324 case RAD_FRAMED_MTU:
325 r->mtu = rad_cvt_int(data);
326 log_Printf(LogPHASE, " MTU %lu\n", r->mtu);
327 break;
328
329 case RAD_FRAMED_ROUTING:
330 /* Disabled for now - should we automatically set up some filters ? */
331 /* rad_cvt_int(data); */
332 /* bit 1 = Send routing packets */
333 /* bit 2 = Receive routing packets */
334 break;
335
336 case RAD_FRAMED_COMPRESSION:
337 r->vj = rad_cvt_int(data) == 1 ? 1 : 0;
338 log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis");
339 break;
340
341 case RAD_FRAMED_ROUTE:
342 /*
343 * We expect a string of the format ``dest[/bits] gw [metrics]''
344 * Any specified metrics are ignored. MYADDR and HISADDR are
345 * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same
346 * as ``HISADDR''.
347 */
348
349 if ((nuke = rad_cvt_string(data, len)) == NULL) {
350 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
351 auth_Failure(r->cx.auth);
352 rad_close(r->cx.rad);
353 return;
354 }
355
356 log_Printf(LogPHASE, " Route: %s\n", nuke);
357 bundle = r->cx.auth->physical->dl->bundle;
358 ip.s_addr = INADDR_ANY;
359 ncprange_setip4host(&dest, ip);
360 argc = command_Interpret(nuke, strlen(nuke), argv);
361 if (argc < 0)
362 log_Printf(LogWARN, "radius: %s: Syntax error\n",
363 argc == 1 ? argv[0] : "\"\"");
364 else if (argc < 2)
365 log_Printf(LogWARN, "radius: %s: Invalid route\n",
366 argc == 1 ? argv[0] : "\"\"");
367 else if ((strcasecmp(argv[0], "default") != 0 &&
368 !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
369 !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
370 log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
371 argv[0], argv[1]);
372 else {
373 ncprange_getwidth(&dest, &width);
374 if (width == 32 && strchr(argv[0], '/') == NULL) {
375 /* No mask specified - use the natural mask */
376 ncprange_getip4addr(&dest, &ip);
377 ncprange_setip4mask(&dest, addr2mask(ip));
378 }
379 addrs = 0;
380
381 if (!strncasecmp(argv[0], "HISADDR", 7))
382 addrs = ROUTE_DSTHISADDR;
383 else if (!strncasecmp(argv[0], "MYADDR", 6))
384 addrs = ROUTE_DSTMYADDR;
385
386 if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) {
387 addrs |= ROUTE_GWHISADDR;
388 ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip);
389 } else if (strcasecmp(argv[1], "HISADDR") == 0)
390 addrs |= ROUTE_GWHISADDR;
391
392 route_Add(&r->routes, addrs, &dest, &gw);
393 }
394 free(nuke);
395 break;
396
397 case RAD_REPLY_MESSAGE:
398 free(r->repstr);
399 if ((r->repstr = rad_cvt_string(data, len)) == NULL) {
400 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
401 auth_Failure(r->cx.auth);
402 rad_close(r->cx.rad);
403 return;
404 }
405 log_Printf(LogPHASE, " Reply-Message \"%s\"\n", r->repstr);
406 break;
407
408 case RAD_VENDOR_SPECIFIC:
409 if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) {
410 log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n",
411 rad_strerror(r->cx.rad));
412 auth_Failure(r->cx.auth);
413 rad_close(r->cx.rad);
414 return;
415 }
416
417 switch (vendor) {
418 case RAD_VENDOR_MICROSOFT:
419 switch (res) {
420 #ifndef NODES
421 case RAD_MICROSOFT_MS_CHAP_ERROR:
422 free(r->errstr);
423 if (len == 0)
424 r->errstr = NULL;
425 else {
426 if (len < 3 || ((const char *)data)[1] != '=') {
427 /*
428 * Only point at the String field if we don't think the
429 * peer has misformatted the response.
430 */
431 const char *foo = (const char *)data + 1;
432 data = (const void *)foo;
433 len--;
434 } else
435 log_Printf(LogWARN, "Warning: The MS-CHAP-Error "
436 "attribute is mis-formatted. Compensating\n");
437 if ((r->errstr = rad_cvt_string((const char *)data,
438 len)) == NULL) {
439 log_Printf(LogERROR, "rad_cvt_string: %s\n",
440 rad_strerror(r->cx.rad));
441 auth_Failure(r->cx.auth);
442 rad_close(r->cx.rad);
443 return;
444 }
445 log_Printf(LogPHASE, " MS-CHAP-Error \"%s\"\n", r->errstr);
446 }
447 break;
448
449 case RAD_MICROSOFT_MS_CHAP2_SUCCESS:
450 free(r->msrepstr);
451 if (len == 0)
452 r->msrepstr = NULL;
453 else {
454 if (len < 3 || ((const char *)data)[1] != '=') {
455 /*
456 * Only point at the String field if we don't think the
457 * peer has misformatted the response.
458 */
459 const char *foo = (const char *)data + 1;
460 data = (const void *)foo;
461 len--;
462 } else
463 log_Printf(LogWARN, "Warning: The MS-CHAP2-Success "
464 "attribute is mis-formatted. Compensating\n");
465 if ((r->msrepstr = rad_cvt_string((const char *)data,
466 len)) == NULL) {
467 log_Printf(LogERROR, "rad_cvt_string: %s\n",
468 rad_strerror(r->cx.rad));
469 auth_Failure(r->cx.auth);
470 rad_close(r->cx.rad);
471 return;
472 }
473 log_Printf(LogPHASE, " MS-CHAP2-Success \"%s\"\n",
474 r->msrepstr);
475 }
476 break;
477
478 case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
479 r->mppe.policy = rad_cvt_int(data);
480 log_Printf(LogPHASE, " MS-MPPE-Encryption-Policy %s\n",
481 radius_policyname(r->mppe.policy));
482 break;
483
484 case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
485 r->mppe.types = rad_cvt_int(data);
486 log_Printf(LogPHASE, " MS-MPPE-Encryption-Types %s\n",
487 radius_typesname(r->mppe.types));
488 break;
489
490 case RAD_MICROSOFT_MS_MPPE_RECV_KEY:
491 free(r->mppe.recvkey);
492 demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen);
493 log_Printf(LogPHASE, " MS-MPPE-Recv-Key ********\n");
494 break;
495
496 case RAD_MICROSOFT_MS_MPPE_SEND_KEY:
497 demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen);
498 log_Printf(LogPHASE, " MS-MPPE-Send-Key ********\n");
499 break;
500 #endif
501
502 default:
503 log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
504 "RADIUS attribute %d\n", res);
505 break;
506 }
507 break;
508
509 default:
510 log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n",
511 (unsigned long)vendor, res);
512 break;
513 }
514 break;
515
516 default:
517 log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res);
518 break;
519 }
520 }
521
522 if (res == -1) {
523 log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n",
524 rad_strerror(r->cx.rad));
525 auth_Failure(r->cx.auth);
526 } else if (got == RAD_ACCESS_REJECT)
527 auth_Failure(r->cx.auth);
528 else {
529 r->valid = 1;
530 auth_Success(r->cx.auth);
531 }
532 rad_close(r->cx.rad);
533 }
534
535 /*
536 * We've either timed out or select()ed on the read descriptor
537 */
538 static void
radius_Continue(struct radius * r,int sel)539 radius_Continue(struct radius *r, int sel)
540 {
541 struct timeval tv;
542 int got;
543
544 timer_Stop(&r->cx.timer);
545 if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) {
546 log_Printf(LogPHASE, "Radius: Request re-sent\n");
547 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
548 timer_Start(&r->cx.timer);
549 return;
550 }
551
552 radius_Process(r, got);
553 }
554
555 /*
556 * Time to call rad_continue_send_request() - timed out.
557 */
558 static void
radius_Timeout(void * v)559 radius_Timeout(void *v)
560 {
561 radius_Continue((struct radius *)v, 0);
562 }
563
564 /*
565 * Time to call rad_continue_send_request() - something to read.
566 */
567 static void
radius_Read(struct fdescriptor * d,struct bundle * bundle,const fd_set * fdset)568 radius_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
569 {
570 radius_Continue(descriptor2radius(d), 1);
571 }
572
573 /*
574 * Behave as a struct fdescriptor (descriptor.h)
575 */
576 static int
radius_UpdateSet(struct fdescriptor * d,fd_set * r,fd_set * w,fd_set * e,int * n)577 radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
578 {
579 struct radius *rad = descriptor2radius(d);
580
581 if (r && rad->cx.fd != -1) {
582 FD_SET(rad->cx.fd, r);
583 if (*n < rad->cx.fd + 1)
584 *n = rad->cx.fd + 1;
585 log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd);
586 return 1;
587 }
588
589 return 0;
590 }
591
592 /*
593 * Behave as a struct fdescriptor (descriptor.h)
594 */
595 static int
radius_IsSet(struct fdescriptor * d,const fd_set * fdset)596 radius_IsSet(struct fdescriptor *d, const fd_set *fdset)
597 {
598 struct radius *r = descriptor2radius(d);
599
600 return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset);
601 }
602
603 /*
604 * Behave as a struct fdescriptor (descriptor.h)
605 */
606 static int
radius_Write(struct fdescriptor * d,struct bundle * bundle,const fd_set * fdset)607 radius_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
608 {
609 /* We never want to write here ! */
610 log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n");
611 return 0;
612 }
613
614 /*
615 * Initialise ourselves
616 */
617 void
radius_Init(struct radius * r)618 radius_Init(struct radius *r)
619 {
620 r->desc.type = RADIUS_DESCRIPTOR;
621 r->desc.UpdateSet = radius_UpdateSet;
622 r->desc.IsSet = radius_IsSet;
623 r->desc.Read = radius_Read;
624 r->desc.Write = radius_Write;
625 r->cx.fd = -1;
626 r->cx.rad = NULL;
627 memset(&r->cx.timer, '\0', sizeof r->cx.timer);
628 r->cx.auth = NULL;
629 r->valid = 0;
630 r->vj = 0;
631 r->ip.s_addr = INADDR_ANY;
632 r->mask.s_addr = INADDR_NONE;
633 r->routes = NULL;
634 r->mtu = DEF_MTU;
635 r->msrepstr = NULL;
636 r->repstr = NULL;
637 r->errstr = NULL;
638 r->mppe.policy = 0;
639 r->mppe.types = 0;
640 r->mppe.recvkey = NULL;
641 r->mppe.recvkeylen = 0;
642 r->mppe.sendkey = NULL;
643 r->mppe.sendkeylen = 0;
644 *r->cfg.file = '\0';
645 log_Printf(LogDEBUG, "Radius: radius_Init\n");
646 }
647
648 /*
649 * Forget everything and go back to initialised state.
650 */
651 void
radius_Destroy(struct radius * r)652 radius_Destroy(struct radius *r)
653 {
654 r->valid = 0;
655 log_Printf(LogDEBUG, "Radius: radius_Destroy\n");
656 timer_Stop(&r->cx.timer);
657 route_DeleteAll(&r->routes);
658 free(r->filterid);
659 r->filterid = NULL;
660 free(r->msrepstr);
661 r->msrepstr = NULL;
662 free(r->repstr);
663 r->repstr = NULL;
664 free(r->errstr);
665 r->errstr = NULL;
666 free(r->mppe.recvkey);
667 r->mppe.recvkey = NULL;
668 r->mppe.recvkeylen = 0;
669 free(r->mppe.sendkey);
670 r->mppe.sendkey = NULL;
671 r->mppe.sendkeylen = 0;
672 if (r->cx.fd != -1) {
673 r->cx.fd = -1;
674 rad_close(r->cx.rad);
675 }
676 }
677
678 static int
radius_put_physical_details(struct rad_handle * rad,struct physical * p)679 radius_put_physical_details(struct rad_handle *rad, struct physical *p)
680 {
681 int slot, type;
682
683 type = RAD_VIRTUAL;
684 if (p->handler)
685 switch (p->handler->type) {
686 case I4B_DEVICE:
687 type = RAD_ISDN_SYNC;
688 break;
689
690 case TTY_DEVICE:
691 type = RAD_ASYNC;
692 break;
693
694 case ETHER_DEVICE:
695 type = RAD_ETHERNET;
696 break;
697
698 case TCP_DEVICE:
699 case UDP_DEVICE:
700 case EXEC_DEVICE:
701 case ATM_DEVICE:
702 case NG_DEVICE:
703 type = RAD_VIRTUAL;
704 break;
705 }
706
707 if (rad_put_int(rad, RAD_NAS_PORT_TYPE, type) != 0) {
708 log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad));
709 rad_close(rad);
710 return 0;
711 }
712
713 if ((slot = physical_Slot(p)) >= 0)
714 if (rad_put_int(rad, RAD_NAS_PORT, slot) != 0) {
715 log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad));
716 rad_close(rad);
717 return 0;
718 }
719
720 return 1;
721 }
722
723 /*
724 * Start an authentication request to the RADIUS server.
725 */
726 int
radius_Authenticate(struct radius * r,struct authinfo * authp,const char * name,const char * key,int klen,const char * nchallenge,int nclen)727 radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
728 const char *key, int klen, const char *nchallenge,
729 int nclen)
730 {
731 struct timeval tv;
732 int got;
733 char hostname[MAXHOSTNAMELEN];
734 #if 0
735 struct hostent *hp;
736 struct in_addr hostaddr;
737 #endif
738 #ifndef NODES
739 struct mschap_response msresp;
740 struct mschap2_response msresp2;
741 const struct MSCHAPv2_resp *keyv2;
742 #endif
743
744 if (!*r->cfg.file)
745 return 0;
746
747 if (r->cx.fd != -1)
748 /*
749 * We assume that our name/key/challenge is the same as last time,
750 * and just continue to wait for the RADIUS server(s).
751 */
752 return 1;
753
754 radius_Destroy(r);
755
756 if ((r->cx.rad = rad_auth_open()) == NULL) {
757 log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
758 return 0;
759 }
760
761 if (rad_config(r->cx.rad, r->cfg.file) != 0) {
762 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
763 rad_close(r->cx.rad);
764 return 0;
765 }
766
767 if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) {
768 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
769 rad_close(r->cx.rad);
770 return 0;
771 }
772
773 if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 ||
774 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
775 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) {
776 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
777 rad_close(r->cx.rad);
778 return 0;
779 }
780
781 switch (authp->physical->link.lcp.want_auth) {
782 case PROTO_PAP:
783 /* We're talking PAP */
784 if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) {
785 log_Printf(LogERROR, "PAP: rad_put_string: %s\n",
786 rad_strerror(r->cx.rad));
787 rad_close(r->cx.rad);
788 return 0;
789 }
790 break;
791
792 case PROTO_CHAP:
793 switch (authp->physical->link.lcp.want_authtype) {
794 case 0x5:
795 if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 ||
796 rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) {
797 log_Printf(LogERROR, "CHAP: rad_put_string: %s\n",
798 rad_strerror(r->cx.rad));
799 rad_close(r->cx.rad);
800 return 0;
801 }
802 break;
803
804 #ifndef NODES
805 case 0x80:
806 if (klen != 50) {
807 log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen);
808 rad_close(r->cx.rad);
809 return 0;
810 }
811
812 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
813 RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
814 msresp.ident = *key;
815 msresp.flags = 0x01;
816 memcpy(msresp.lm_response, key + 1, 24);
817 memcpy(msresp.nt_response, key + 25, 24);
818 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
819 RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp,
820 sizeof msresp);
821 break;
822
823 case 0x81:
824 if (klen != sizeof(*keyv2) + 1) {
825 log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen);
826 rad_close(r->cx.rad);
827 return 0;
828 }
829
830 keyv2 = (const struct MSCHAPv2_resp *)(key + 1);
831 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
832 RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
833 msresp2.ident = *key;
834 msresp2.flags = keyv2->Flags;
835 memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response);
836 memset(msresp2.reserved, '\0', sizeof msresp2.reserved);
837 memcpy(msresp2.pchallenge, keyv2->PeerChallenge,
838 sizeof msresp2.pchallenge);
839 rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
840 RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2,
841 sizeof msresp2);
842 break;
843 #endif
844 default:
845 log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n",
846 authp->physical->link.lcp.want_authtype);
847 rad_close(r->cx.rad);
848 return 0;
849 }
850 }
851
852 if (gethostname(hostname, sizeof hostname) != 0)
853 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
854 else {
855 #if 0
856 if ((hp = gethostbyname(hostname)) != NULL) {
857 hostaddr.s_addr = *(u_long *)hp->h_addr;
858 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
859 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
860 rad_strerror(r->cx.rad));
861 rad_close(r->cx.rad);
862 return 0;
863 }
864 }
865 #endif
866 if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
867 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
868 rad_strerror(r->cx.rad));
869 rad_close(r->cx.rad);
870 return 0;
871 }
872 }
873
874 radius_put_physical_details(r->cx.rad, authp->physical);
875
876 r->cx.auth = authp;
877 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
878 radius_Process(r, got);
879 else {
880 log_Printf(LogPHASE, "Radius: Request sent\n");
881 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
882 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
883 r->cx.timer.func = radius_Timeout;
884 r->cx.timer.name = "radius auth";
885 r->cx.timer.arg = r;
886 timer_Start(&r->cx.timer);
887 }
888
889 return 1;
890 }
891
892 /*
893 * Send an accounting request to the RADIUS server
894 */
895 void
radius_Account(struct radius * r,struct radacct * ac,struct datalink * dl,int acct_type,struct in_addr * peer_ip,struct in_addr * netmask,struct pppThroughput * stats)896 radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl,
897 int acct_type, struct in_addr *peer_ip, struct in_addr *netmask,
898 struct pppThroughput *stats)
899 {
900 struct timeval tv;
901 int got;
902 char hostname[MAXHOSTNAMELEN];
903 #if 0
904 struct hostent *hp;
905 struct in_addr hostaddr;
906 #endif
907
908 if (!*r->cfg.file)
909 return;
910
911 if (r->cx.fd != -1)
912 /*
913 * We assume that our name/key/challenge is the same as last time,
914 * and just continue to wait for the RADIUS server(s).
915 */
916 return;
917
918 timer_Stop(&r->cx.timer);
919
920 if ((r->cx.rad = rad_acct_open()) == NULL) {
921 log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
922 return;
923 }
924
925 if (rad_config(r->cx.rad, r->cfg.file) != 0) {
926 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
927 rad_close(r->cx.rad);
928 return;
929 }
930
931 if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) {
932 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
933 rad_close(r->cx.rad);
934 return;
935 }
936
937 /* Grab some accounting data and initialize structure */
938 if (acct_type == RAD_START) {
939 ac->rad_parent = r;
940 /* Fetch username from datalink */
941 strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name);
942 ac->user_name[AUTHLEN-1] = '\0';
943
944 ac->authentic = 2; /* Assume RADIUS verified auth data */
945
946 /* Generate a session ID */
947 snprintf(ac->session_id, sizeof ac->session_id, "%s%ld-%s%lu",
948 dl->bundle->cfg.auth.name, (long)getpid(),
949 dl->peer.authname, (unsigned long)stats->uptime);
950
951 /* And grab our MP socket name */
952 snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s",
953 dl->bundle->ncp.mp.active ?
954 dl->bundle->ncp.mp.server.socket.sun_path : "");
955
956 /* Fetch IP, netmask from IPCP */
957 memcpy(&ac->ip, peer_ip, sizeof(ac->ip));
958 memcpy(&ac->mask, netmask, sizeof(ac->mask));
959 };
960
961 if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 ||
962 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
963 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0 ||
964 rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS, ac->ip) != 0 ||
965 rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK, ac->mask) != 0) {
966 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
967 rad_close(r->cx.rad);
968 return;
969 }
970
971 if (gethostname(hostname, sizeof hostname) != 0)
972 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
973 else {
974 #if 0
975 if ((hp = gethostbyname(hostname)) != NULL) {
976 hostaddr.s_addr = *(u_long *)hp->h_addr;
977 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
978 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
979 rad_strerror(r->cx.rad));
980 rad_close(r->cx.rad);
981 return;
982 }
983 }
984 #endif
985 if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
986 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
987 rad_strerror(r->cx.rad));
988 rad_close(r->cx.rad);
989 return;
990 }
991 }
992
993 radius_put_physical_details(r->cx.rad, dl->physical);
994
995 if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 ||
996 rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 ||
997 rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID,
998 ac->multi_session_id) != 0 ||
999 rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) {
1000 /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */
1001 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1002 rad_close(r->cx.rad);
1003 return;
1004 }
1005
1006 if (acct_type == RAD_STOP)
1007 /* Show some statistics */
1008 if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn) != 0 ||
1009 rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 ||
1010 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut) != 0 ||
1011 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut)
1012 != 0 ||
1013 rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats))
1014 != 0) {
1015 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
1016 rad_close(r->cx.rad);
1017 return;
1018 }
1019
1020 r->cx.auth = NULL; /* Not valid for accounting requests */
1021 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
1022 radius_Process(r, got);
1023 else {
1024 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
1025 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
1026 r->cx.timer.func = radius_Timeout;
1027 r->cx.timer.name = "radius acct";
1028 r->cx.timer.arg = r;
1029 timer_Start(&r->cx.timer);
1030 }
1031 }
1032
1033 /*
1034 * How do things look at the moment ?
1035 */
1036 void
radius_Show(struct radius * r,struct prompt * p)1037 radius_Show(struct radius *r, struct prompt *p)
1038 {
1039 prompt_Printf(p, " Radius config: %s",
1040 *r->cfg.file ? r->cfg.file : "none");
1041 if (r->valid) {
1042 prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip));
1043 prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask));
1044 prompt_Printf(p, " MTU: %lu\n", r->mtu);
1045 prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis");
1046 prompt_Printf(p, " Message: %s\n", r->repstr ? r->repstr : "");
1047 prompt_Printf(p, " MPPE Enc Policy: %s\n",
1048 radius_policyname(r->mppe.policy));
1049 prompt_Printf(p, " MPPE Enc Types: %s\n",
1050 radius_typesname(r->mppe.types));
1051 prompt_Printf(p, " MPPE Recv Key: %seceived\n",
1052 r->mppe.recvkey ? "R" : "Not r");
1053 prompt_Printf(p, " MPPE Send Key: %seceived\n",
1054 r->mppe.sendkey ? "R" : "Not r");
1055 prompt_Printf(p, " MS-CHAP2-Response: %s\n",
1056 r->msrepstr ? r->msrepstr : "");
1057 prompt_Printf(p, " Error Message: %s\n", r->errstr ? r->errstr : "");
1058 if (r->routes)
1059 route_ShowSticky(p, r->routes, " Routes", 16);
1060 } else
1061 prompt_Printf(p, " (not authenticated)\n");
1062 }
1063