allow compilation with BGP unset
[l2tpns.git] / radius.c
1 // L2TPNS Radius Stuff
2
3 char const *cvs_id_radius = "$Id: radius.c,v 1.19 2004-11-30 06:50:26 bodea Exp $";
4
5 #include <time.h>
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include <malloc.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <arpa/inet.h>
13 #include <ctype.h>
14 #include <netinet/in.h>
15 #include "md5.h"
16 #include "constants.h"
17 #include "l2tpns.h"
18 #include "plugin.h"
19 #include "util.h"
20
21 extern radiust *radius;
22 extern sessiont *session;
23 extern tunnelt *tunnel;
24 extern u32 sessionid;
25 extern configt *config;
26 extern int *radfds;
27 extern ip_filtert *ip_filters;
28
29 static const char *radius_state(int state)
30 {
31 static char *tmp = NULL;
32 int i;
33 for (i = 0; radius_states[i]; i++)
34 if (i == state) return radius_states[i];
35
36 if (tmp == NULL) tmp = (char *)calloc(64, 1);
37 sprintf(tmp, "%d", state);
38 return tmp;
39 }
40
41 // Set up socket for radius requests
42 void initrad(void)
43 {
44 int i;
45 LOG(3, 0, 0, "Creating %d sockets for RADIUS queries\n", config->num_radfds);
46 radfds = calloc(sizeof(int), config->num_radfds);
47 for (i = 0; i < config->num_radfds; i++)
48 {
49 int flags;
50 radfds[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
51 flags = fcntl(radfds[i], F_GETFL, 0);
52 fcntl(radfds[i], F_SETFL, flags | O_NONBLOCK);
53 }
54 }
55
56 void radiusclear(u16 r, sessionidt s)
57 {
58 if (s) session[s].radius = 0;
59 memset(&radius[r], 0, sizeof(radius[r])); // radius[r].state = RADIUSNULL;
60 }
61
62
63 static u16 get_free_radius()
64 {
65 int count;
66 static u32 next_radius_id = 0;
67
68 for (count = MAXRADIUS; count > 0 ; --count)
69 {
70 ++next_radius_id; // Find the next ID to check.
71 if (next_radius_id >= MAXRADIUS)
72 next_radius_id = 1;
73
74 if (radius[next_radius_id].state == RADIUSNULL)
75 {
76 return next_radius_id;
77 }
78 }
79
80 LOG(0, 0, 0, "Can't find a free radius session! This is very bad!\n");
81 return 0;
82 }
83
84 u16 radiusnew(sessionidt s)
85 {
86 u16 r = session[s].radius;
87
88 /* re-use */
89 if (r)
90 {
91 LOG(3, s, session[s].tunnel, "Re-used radius %d\n", r);
92 return r;
93 }
94
95 if (!(r = get_free_radius()))
96 {
97 LOG(1, s, session[s].tunnel, "No free RADIUS sessions\n");
98 STAT(radius_overflow);
99 return 0;
100 };
101
102 memset(&radius[r], 0, sizeof(radius[r]));
103 session[s].radius = r;
104 radius[r].session = s;
105 radius[r].state = RADIUSWAIT;
106 radius[r].retry = TIME + 1200; // Wait at least 120 seconds to re-claim this.
107
108 LOG(3, s, session[s].tunnel, "Allocated radius %d\n", r);
109 return r;
110 }
111
112 // Send a RADIUS request
113 void radiussend(u16 r, u8 state)
114 {
115 struct sockaddr_in addr;
116 u8 b[4096]; // RADIUS packet
117 char pass[129];
118 int pl;
119 u8 *p;
120 sessionidt s;
121
122 CSTAT(call_radiussend);
123
124 s = radius[r].session;
125 if (!config->numradiusservers)
126 {
127 LOG(0, s, session[s].tunnel, "No RADIUS servers\n");
128 return;
129 }
130 if (!*config->radiussecret)
131 {
132 LOG(0, s, session[s].tunnel, "No RADIUS secret\n");
133 return;
134 }
135
136 if (state != RADIUSAUTH && !config->radius_accounting)
137 {
138 // Radius accounting is turned off
139 radiusclear(r, s);
140 return;
141 }
142
143 if (radius[r].state != state)
144 radius[r].try = 0;
145 radius[r].state = state;
146 radius[r].retry = backoff(radius[r].try++);
147 LOG(4, s, session[s].tunnel, "Send RADIUS id %d sock %d state %s try %d\n",
148 r >> RADIUS_SHIFT, r & RADIUS_MASK,
149 radius_state(radius[r].state), radius[r].try);
150
151 if (radius[r].try > config->numradiusservers * 2)
152 {
153 if (s)
154 {
155 if (state == RADIUSAUTH)
156 sessionshutdown(s, "RADIUS timeout");
157 else
158 {
159 LOG(1, s, session[s].tunnel, "RADIUS timeout, but in state %s so don't timeout session\n",
160 radius_states[state]);
161 radiusclear(r, s);
162 }
163 STAT(radius_timeout);
164 }
165 else
166 {
167 STAT(radius_retries);
168 radius[r].state = RADIUSWAIT;
169 radius[r].retry = 100;
170 }
171 return ;
172 }
173 // contruct RADIUS access request
174 switch (state)
175 {
176 case RADIUSAUTH:
177 b[0] = 1; // access request
178 break;
179 case RADIUSSTART:
180 case RADIUSSTOP:
181 b[0] = 4; // accounting request
182 break;
183 default:
184 LOG(0, 0, 0, "Unknown radius state %d\n", state);
185 }
186 b[1] = r >> RADIUS_SHIFT; // identifier
187 memcpy(b + 4, radius[r].auth, 16);
188 p = b + 20;
189 if (s)
190 {
191 *p = 1; // user name
192 p[1] = strlen(session[s].user) + 2;
193 strcpy(p + 2, session[s].user);
194 p += p[1];
195 }
196 if (state == RADIUSAUTH)
197 {
198 if (radius[r].chap)
199 {
200 *p = 3; // CHAP password
201 p[1] = 19; // length
202 p[2] = radius[r].id; // ID
203 memcpy(p + 3, radius[r].pass, 16); // response from CHAP request
204 p += p[1];
205 *p = 60; // CHAP Challenge
206 p[1] = 18; // length
207 memcpy(p + 2, radius[r].auth, 16);
208 p += p[1];
209 }
210 else
211 {
212 strcpy(pass, radius[r].pass);
213 pl = strlen(pass);
214 while (pl & 15)
215 pass[pl++] = 0; // pad
216 if (pl)
217 { // encrypt
218 hasht hash;
219 int p = 0;
220 while (p < pl)
221 {
222 MD5_CTX ctx;
223 MD5Init(&ctx);
224 MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
225 if (p)
226 MD5Update(&ctx, pass + p - 16, 16);
227 else
228 MD5Update(&ctx, radius[r].auth, 16);
229 MD5Final(hash, &ctx);
230 do
231 {
232 pass[p] ^= hash[p & 15];
233 p++;
234 }
235 while (p & 15);
236 }
237 }
238 *p = 2; // password
239 p[1] = pl + 2;
240 if (pl)
241 memcpy(p + 2, pass, pl);
242 p += p[1];
243 }
244 }
245 else if (state == RADIUSSTART || state == RADIUSSTOP)
246 { // accounting
247 *p = 40; // accounting type
248 p[1] = 6;
249 *(u32 *) (p + 2) = htonl((state == RADIUSSTART) ? 1 : 2);
250 p += p[1];
251 if (s)
252 {
253 *p = 44; // session ID
254 p[1] = 18;
255 sprintf(p + 2, "%08X%08X", session[s].id, session[s].opened);
256 p += p[1];
257 if (state == RADIUSSTOP)
258 { // stop
259 *p = 42; // input octets
260 p[1] = 6;
261 *(u32 *) (p + 2) = htonl(session[s].cin);
262 p += p[1];
263 *p = 43; // output octets
264 p[1] = 6;
265 *(u32 *) (p + 2) = htonl(session[s].cout);
266 p += p[1];
267 *p = 46; // session time
268 p[1] = 6;
269 *(u32 *) (p + 2) = htonl(time(NULL) - session[s].opened);
270 p += p[1];
271 *p = 47; // input packets
272 p[1] = 6;
273 *(u32 *) (p + 2) = htonl(session[s].pin);
274 p += p[1];
275 *p = 48; // output spackets
276 p[1] = 6;
277 *(u32 *) (p + 2) = htonl(session[s].pout);
278 p += p[1];
279 }
280 else
281 { // start
282 *p = 41; // delay
283 p[1] = 6;
284 *(u32 *) (p + 2) = htonl(time(NULL) - session[s].opened);
285 p += p[1];
286 }
287 }
288 }
289 if (s)
290 {
291 *p = 5; // NAS-Port
292 p[1] = 6;
293 *(u32 *) (p + 2) = htonl(s);
294 p += p[1];
295 }
296 if (s && session[s].ip)
297 {
298 *p = 8; // Framed-IP-Address
299 p[1] = 6;
300 *(u32 *) (p + 2) = htonl(session[s].ip);
301 p += p[1];
302 }
303 if (*session[s].called)
304 {
305 *p = 30; // called
306 p[1] = strlen(session[s].called) + 2;
307 strcpy(p + 2, session[s].called);
308 p += p[1];
309 }
310 if (*radius[r].calling)
311 {
312 *p = 31; // calling
313 p[1] = strlen(radius[r].calling) + 2;
314 strcpy(p + 2, radius[r].calling);
315 p += p[1];
316 }
317 else if (*session[s].calling)
318 {
319 *p = 31; // calling
320 p[1] = strlen(session[s].calling) + 2;
321 strcpy(p + 2, session[s].calling);
322 p += p[1];
323 }
324 // NAS-IP-Address
325 *p = 4;
326 p[1] = 6;
327 *(u32 *)(p + 2) = config->bind_address;
328 p += p[1];
329
330 // All AVpairs added
331 *(u16 *) (b + 2) = htons(p - b);
332 if (state != RADIUSAUTH)
333 {
334 // Build auth for accounting packet
335 char z[16] = {0};
336 char hash[16] = {0};
337 MD5_CTX ctx;
338 MD5Init(&ctx);
339 MD5Update(&ctx, b, 4);
340 MD5Update(&ctx, z, 16);
341 MD5Update(&ctx, b + 20, (p - b) - 20);
342 MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
343 MD5Final(hash, &ctx);
344 memcpy(b + 4, hash, 16);
345 memcpy(radius[r].auth, hash, 16);
346 }
347 memset(&addr, 0, sizeof(addr));
348 addr.sin_family = AF_INET;
349 *(u32 *) & addr.sin_addr = config->radiusserver[(radius[r].try - 1) % config->numradiusservers];
350 {
351 // get radius port
352 u16 port = config->radiusport[(radius[r].try - 1) % config->numradiusservers];
353 // no need to define the accounting port for itself:
354 // the accounting port is as far as I know always one more
355 // than the auth port JK 20040713
356 addr.sin_port = htons((state == RADIUSAUTH) ? port : port+1);
357 }
358
359 LOG_HEX(5, "RADIUS Send", b, (p - b));
360 sendto(radfds[r & RADIUS_MASK], b, p - b, 0, (void *) &addr, sizeof(addr));
361 }
362
363 // process RADIUS response
364 void processrad(u8 *buf, int len, char socket_index)
365 {
366 u8 b[MAXCONTROL];
367 MD5_CTX ctx;
368 u16 r;
369 sessionidt s;
370 tunnelidt t = 0;
371 hasht hash;
372 u8 routes = 0;
373
374 int r_code, r_id ; // Radius code.
375
376 r_code = buf[0]; // First byte in radius packet.
377 r_id = buf[1]; // radius reply indentifier.
378
379
380 CSTAT(call_processrad);
381
382 LOG_HEX(5, "RADIUS Response", buf, len);
383 if (len < 20 || len < ntohs(*(u16 *) (buf + 2)))
384 {
385 LOG(1, 0, 0, "Duff RADIUS response length %d\n", len);
386 return ;
387 }
388 len = ntohs(*(u16 *) (buf + 2));
389 r = socket_index | (r_id << RADIUS_SHIFT);
390 s = radius[r].session;
391 LOG(3, s, session[s].tunnel, "Received %s, radius %d response for session %u (code %d, id %d)\n",
392 radius_states[radius[r].state], r, s, r_code, r_id);
393 if (!s && radius[r].state != RADIUSSTOP)
394 {
395 LOG(1, s, session[s].tunnel, " Unexpected RADIUS response\n");
396 return;
397 }
398 if (radius[r].state != RADIUSAUTH && radius[r].state != RADIUSSTART && radius[r].state != RADIUSSTOP)
399 {
400 LOG(1, s, session[s].tunnel, " Unexpected RADIUS response\n");
401 return;
402 }
403 t = session[s].tunnel;
404 MD5Init(&ctx);
405 MD5Update(&ctx, buf, 4);
406 MD5Update(&ctx, radius[r].auth, 16);
407 MD5Update(&ctx, buf + 20, len - 20);
408 MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
409 MD5Final(hash, &ctx);
410 do {
411 if (memcmp(hash, buf + 4, 16))
412 {
413 LOG(0, s, session[s].tunnel, " Incorrect auth on RADIUS response!! (wrong secret in radius config?)\n");
414 return; // Do nothing. On timeout, it will try the next radius server.
415 }
416 if ((radius[r].state == RADIUSAUTH && *buf != 2 && *buf != 3) ||
417 ((radius[r].state == RADIUSSTART || radius[r].state == RADIUSSTOP) && *buf != 5))
418 {
419 LOG(1, s, session[s].tunnel, " Unexpected RADIUS response %d\n", *buf);
420 return; // We got something we didn't expect. Let the timeouts take
421 // care off finishing the radius session if that's really correct.
422 }
423 if (radius[r].state == RADIUSAUTH)
424 {
425 LOG(4, s, session[s].tunnel, " Original response is \"%s\"\n", (*buf == 2) ? "accept" : "reject");
426 // process auth response
427 if (radius[r].chap)
428 {
429 // CHAP
430 u8 *p = makeppp(b, sizeof(b), 0, 0, t, s, PPPCHAP);
431 if (!p) return; // Abort!
432
433 {
434 struct param_post_auth packet = { &tunnel[t], &session[s], session[s].user, (*buf == 2), PPPCHAP };
435 run_plugins(PLUGIN_POST_AUTH, &packet);
436 *buf = packet.auth_allowed ? 2 : 3;
437 }
438
439 LOG(3, s, session[s].tunnel, " CHAP User %s authentication %s.\n", session[s].user,
440 (*buf == 2) ? "allowed" : "denied");
441 *p = (*buf == 2) ? 3 : 4; // ack/nak
442 p[1] = radius[r].id;
443 *(u16 *) (p + 2) = ntohs(4); // no message
444 tunnelsend(b, (p - b) + 4, t); // send it
445 }
446 else
447 {
448 // PAP
449 u8 *p = makeppp(b, sizeof(b), 0, 0, t, s, PPPPAP);
450 if (!p) return; // Abort!
451
452 {
453 struct param_post_auth packet = { &tunnel[t], &session[s], session[s].user, (*buf == 2), PPPPAP };
454 run_plugins(PLUGIN_POST_AUTH, &packet);
455 *buf = packet.auth_allowed ? 2 : 3;
456 }
457
458 LOG(3, s, session[s].tunnel, " PAP User %s authentication %s.\n", session[s].user,
459 (*buf == 2) ? "allowed" : "denied");
460 // ack/nak
461 *p = *buf;
462 p[1] = radius[r].id;
463 *(u16 *) (p + 2) = ntohs(5);
464 p[4] = 0; // no message
465 tunnelsend(b, (p - b) + 5, t); // send it
466 }
467
468 if (*buf == 2)
469 {
470 // Login successful
471 // Extract IP, routes, etc
472 u8 *p = buf + 20;
473 u8 *e = buf + len;
474 for (; p + 2 <= e && p[1] && p + p[1] <= e; p += p[1])
475 {
476 if (*p == 8)
477 {
478 // Framed-IP-Address
479 if (p[1] < 6) continue;
480 session[s].ip = ntohl(*(u32 *) (p + 2));
481 session[s].ip_pool_index = -1;
482 LOG(3, s, session[s].tunnel, " Radius reply contains IP address %s\n",
483 fmtaddr(htonl(session[s].ip), 0));
484 }
485 else if (*p == 135)
486 {
487 // DNS address
488 if (p[1] < 6) continue;
489 session[s].dns1 = ntohl(*(u32 *) (p + 2));
490 LOG(3, s, session[s].tunnel, " Radius reply contains primary DNS address %s\n",
491 fmtaddr(htonl(session[s].dns1), 0));
492 }
493 else if (*p == 136)
494 {
495 // DNS address
496 if (p[1] < 6) continue;
497 session[s].dns2 = ntohl(*(u32 *) (p + 2));
498 LOG(3, s, session[s].tunnel, " Radius reply contains secondary DNS address %s\n",
499 fmtaddr(htonl(session[s].dns2), 0));
500 }
501 else if (*p == 22)
502 {
503 // Framed-Route
504 ipt ip = 0, mask = 0;
505 u8 u = 0;
506 u8 bits = 0;
507 u8 *n = p + 2;
508 u8 *e = p + p[1];
509 while (n < e && (isdigit(*n) || *n == '.'))
510 {
511 if (*n == '.')
512 {
513 ip = (ip << 8) + u;
514 u = 0;
515 }
516 else
517 u = u * 10 + *n - '0';
518 n++;
519 }
520 ip = (ip << 8) + u;
521 if (*n == '/')
522 {
523 n++;
524 while (n < e && isdigit(*n))
525 bits = bits * 10 + *n++ - '0';
526 mask = (( -1) << (32 - bits));
527 }
528 else if ((ip >> 24) < 128)
529 mask = 0xFF0000;
530 else if ((ip >> 24) < 192)
531 mask = 0xFFFF0000;
532 else
533 mask = 0xFFFFFF00;
534
535 if (routes == MAXROUTE)
536 {
537 LOG(1, s, session[s].tunnel, " Too many routes\n");
538 }
539 else if (ip)
540 {
541 LOG(3, s, session[s].tunnel, " Radius reply contains route for %s/%s\n",
542 fmtaddr(htonl(ip), 0), fmtaddr(htonl(mask), 1));
543
544 session[s].route[routes].ip = ip;
545 session[s].route[routes].mask = mask;
546 routes++;
547 }
548 }
549 else if (*p == 11)
550 {
551 // Filter-Id
552 char *filter = p + 2;
553 int l = p[1] - 2;
554 char *suffix;
555 u8 *f = 0;
556 int i;
557
558 LOG(3, s, session[s].tunnel, " Radius reply contains Filter-Id \"%.*s\"\n", l, filter);
559 if ((suffix = memchr(filter, '.', l)))
560 {
561 int b = suffix - filter;
562 if (l - b == 3 && !memcmp("in", suffix+1, 2))
563 f = &session[s].filter_in;
564 else if (l - b == 4 && !memcmp("out", suffix+1, 3))
565 f = &session[s].filter_out;
566
567 l = b;
568 }
569
570 if (!f)
571 {
572 LOG(3, s, session[s].tunnel, " Invalid filter\n");
573 continue;
574 }
575
576 for (*f = 0, i = 0; !*f && i < MAXFILTER; i++)
577 if (strlen(ip_filters[i].name) == l &&
578 !strncmp(ip_filters[i].name, filter, l))
579 *f = i + 1;
580
581 if (*f)
582 ip_filters[*f - 1].used++;
583 else
584 LOG(3, s, session[s].tunnel, " Unknown filter\n");
585
586 }
587 else if (*p == 26 && p[1] >= 7)
588 {
589 // Vendor-Specific Attribute
590 int vendor = ntohl(*(int *)(p + 2));
591 char attrib = *(p + 6);
592 char attrib_length = *(p + 7) - 2;
593 char *avpair, *value, *key, *newp;
594
595 LOG(3, s, session[s].tunnel, " Radius reply contains Vendor-Specific. Vendor=%d Attrib=%d Length=%d\n", vendor, attrib, attrib_length);
596 if (vendor != 9 || attrib != 1)
597 {
598 LOG(3, s, session[s].tunnel, " Unknown vendor-specific\n");
599 continue;
600 }
601
602 if (attrib_length < 0) continue;
603
604 avpair = key = calloc(attrib_length + 1, 1);
605 memcpy(avpair, p + 8, attrib_length);
606 LOG(3, s, session[s].tunnel, " Cisco-Avpair value: %s\n", avpair);
607 do {
608 value = strchr(key, '=');
609 if (!value) break;
610 *value++ = 0;
611
612 // Trim quotes off reply string
613 if (*value == '\'' || *value == '\"')
614 {
615 char *x;
616 value++;
617 x = value + strlen(value) - 1;
618 if (*x == '\'' || *x == '\"')
619 *x = 0;
620 }
621
622 // Run hooks
623 newp = strchr(value, ',');
624 if (newp) *newp++ = 0;
625 {
626 struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], key, value };
627 run_plugins(PLUGIN_RADIUS_RESPONSE, &p);
628 }
629 key = newp;
630 } while (newp);
631 free(avpair);
632 }
633 }
634 }
635 else if (*buf == 3)
636 {
637 LOG(2, s, session[s].tunnel, " Authentication denied for %s\n", session[s].user);
638 //FIXME: We should tear down the session here!
639 break;
640 }
641
642 if (!session[s].dns1 && config->default_dns1)
643 {
644 session[s].dns1 = htonl(config->default_dns1);
645 LOG(3, s, t, " Sending dns1 = %s\n", fmtaddr(config->default_dns1, 0));
646 }
647 if (!session[s].dns2 && config->default_dns2)
648 {
649 session[s].dns2 = htonl(config->default_dns2);
650 LOG(3, s, t, " Sending dns2 = %s\n", fmtaddr(config->default_dns2, 0));
651 }
652
653 // Valid Session, set it up
654 session[s].unique_id = 0;
655 sessionsetup(t, s);
656 }
657 else
658 {
659 // An ack for a stop or start record.
660 LOG(3, s, t, " RADIUS accounting ack recv in state %s\n", radius_states[radius[r].state]);
661 break;
662 }
663 } while (0);
664
665 // finished with RADIUS
666 radiusclear(r, s);
667 }
668
669 // Send a retry for RADIUS/CHAP message
670 void radiusretry(u16 r)
671 {
672 sessionidt s = radius[r].session;
673 tunnelidt t = 0;
674
675 CSTAT(call_radiusretry);
676
677 if (s)
678 t = session[s].tunnel;
679 radius[r].retry = backoff(radius[r].try + 1);
680 switch (radius[r].state)
681 {
682 case RADIUSCHAP: // sending CHAP down PPP
683 sendchap(t, s);
684 break;
685 case RADIUSIPCP:
686 sendipcp(t, s); // send IPCP
687 break;
688 case RADIUSAUTH: // sending auth to RADIUS server
689 radiussend(r, RADIUSAUTH);
690 break;
691 case RADIUSSTART: // sending start accounting to RADIUS server
692 radiussend(r, RADIUSSTART);
693 break;
694 case RADIUSSTOP: // sending stop accounting to RADIUS server
695 radiussend(r, RADIUSSTOP);
696 break;
697 default:
698 case RADIUSNULL: // Not in use
699 case RADIUSWAIT: // waiting timeout before available, in case delayed reply from RADIUS server
700 // free up RADIUS task
701 radiusclear(r, s);
702 LOG(3, s, session[s].tunnel, "Freeing up radius session %d\n", r);
703 break;
704 }
705 }