ee364b20d094b2bcb3706444c5a1e7adc52f6604
2 // $Id: radius.c,v 1.1 2003/12/16 07:07:39 fred_nerk Exp $
7 #include <sys/socket.h>
10 #include <arpa/inet.h>
12 #include <netinet/in.h>
14 #include "constants.h"
19 extern char *radiussecret
;
20 extern radiust
*radius
;
21 extern sessiont
*session
;
22 extern tunnelt
*tunnel
;
23 extern ipt radiusserver
[MAXRADSERVER
]; // radius servers
27 extern u8 numradiusservers
;
29 extern unsigned long default_dns1
, default_dns2
;
30 extern struct Tstats
*_statistics
;
31 extern int radius_accounting
;
32 extern uint32_t bind_address
;
34 const char *radius_state(int state
)
36 static char *tmp
= NULL
;
38 for (i
= 0; radius_states
[i
]; i
++)
39 if (i
== state
) return radius_states
[i
];
41 if (tmp
== NULL
) tmp
= (char *)calloc(64, 1);
42 sprintf(tmp
, "%d", state
);
46 // Set up socket for radius requests
49 radfd
= socket(AF_INET
, SOCK_DGRAM
, UDP
);
52 void radiusclear(u8 r
, sessionidt s
)
54 radius
[r
].state
= RADIUSNULL
;
55 if (s
) session
[s
].radius
= 0;
56 memset(&radius
[r
], 0, sizeof(radius
[r
]));
57 radius
[r
].next
= radiusfree
;
61 u8
radiusnew(sessionidt s
)
66 log(1, 0, s
, session
[s
].tunnel
, "No free RADIUS sessions\n");
67 STAT(radius_overflow
);
71 session
[s
].radius
= r
;
72 radiusfree
= radius
[r
].next
;
73 memset(&radius
[r
], 0, sizeof(radius
[r
]));
74 radius
[r
].session
= s
;
78 // Send a RADIUS request
79 void radiussend(u8 r
, u8 state
)
81 struct sockaddr_in addr
;
82 u8 b
[4096]; // RADIUS packet
88 STAT(call_radiussend
);
90 if (!numradiusservers
)
92 log(0, 0, 0, 0, "No RADIUS servers\n");
97 log(0, 0, 0, 0, "No RADIUS secret\n");
100 s
= radius
[r
].session
;
102 if (state
!= RADIUSAUTH
&& !radius_accounting
)
104 // Radius accounting is turned off
109 if (radius
[r
].state
!= state
)
111 radius
[r
].state
= state
;
112 radius
[r
].retry
= backoff(radius
[r
].try++);
113 log(4, 0, s
, session
[s
].tunnel
, "Send RADIUS %d state %s try %d\n", r
, radius_state(radius
[r
].state
), radius
[r
].try);
114 if (radius
[r
].try > numradiusservers
* 2)
118 sessionshutdown(s
, "RADIUS timeout");
119 STAT(radius_timeout
);
123 STAT(radius_retries
);
124 radius
[r
].state
= RADIUSWAIT
;
125 radius
[r
].retry
= 100;
129 // contruct RADIUS access request
133 b
[0] = 1; // access request
137 b
[0] = 4; // accounting request
140 log(0, 0, 0, 0, "Unknown radius state %d\n", state
);
142 b
[1] = r
; // identifier
143 memcpy(b
+ 4, radius
[r
].auth
, 16);
148 p
[1] = strlen(session
[s
].user
) + 2;
149 strcpy(p
+ 2, session
[s
].user
);
152 if (state
== RADIUSAUTH
)
156 *p
= 3; // CHAP password
158 p
[2] = radius
[r
].id
; // ID
159 memcpy(p
+ 3, radius
[r
].pass
, 16); // response from CHAP request
161 *p
= 60; // CHAP Challenge
163 memcpy(p
+ 2, radius
[r
].auth
, 16);
168 strcpy(pass
, radius
[r
].pass
);
171 pass
[pl
++] = 0; // pad
180 MD5Update(&ctx
, radiussecret
, strlen(radiussecret
));
182 MD5Update(&ctx
, pass
+ p
- 16, 16);
184 MD5Update(&ctx
, radius
[r
].auth
, 16);
185 MD5Final(hash
, &ctx
);
188 pass
[p
] ^= hash
[p
& 15];
197 memcpy(p
+ 2, pass
, pl
);
201 else if (state
== RADIUSSTART
|| state
== RADIUSSTOP
)
203 *p
= 40; // accounting type
205 *(u32
*) (p
+ 2) = htonl((state
== RADIUSSTART
) ? 1 : 2);
209 *p
= 44; // session ID
211 sprintf(p
+ 2, "%08X%08X", session
[s
].id
, session
[s
].opened
);
213 if (state
== RADIUSSTOP
)
215 *p
= 42; // input octets
217 *(u32
*) (p
+ 2) = htonl(session
[s
].cin
);
219 *p
= 43; // output octets
221 *(u32
*) (p
+ 2) = htonl(session
[s
].cout
);
223 *p
= 46; // session time
225 *(u32
*) (p
+ 2) = htonl(time(NULL
) - session
[s
].opened
);
227 *p
= 47; // input packets
229 *(u32
*) (p
+ 2) = htonl(session
[s
].pin
);
231 *p
= 48; // output spackets
233 *(u32
*) (p
+ 2) = htonl(session
[s
].pout
);
240 *(u32
*) (p
+ 2) = htonl(time(NULL
) - session
[s
].opened
);
249 *(u32
*) (p
+ 2) = htonl(s
);
252 if (s
&& session
[s
].ip
)
254 *p
= 8; // Framed-IP-Address
256 *(u32
*) (p
+ 2) = htonl(session
[s
].ip
);
259 if (*session
[s
].called
)
262 p
[1] = strlen(session
[s
].called
) + 2;
263 strcpy(p
+ 2, session
[s
].called
);
266 if (*radius
[r
].calling
)
269 p
[1] = strlen(radius
[r
].calling
) + 2;
270 strcpy(p
+ 2, radius
[r
].calling
);
273 else if (*session
[s
].calling
)
276 p
[1] = strlen(session
[s
].calling
) + 2;
277 strcpy(p
+ 2, session
[s
].calling
);
283 *(u32
*)(p
+ 2) = bind_address
;
287 *(u16
*) (b
+ 2) = htons(p
- b
);
288 if (state
!= RADIUSAUTH
)
290 // Build auth for accounting packet
295 MD5Update(&ctx
, b
, 4);
296 MD5Update(&ctx
, z
, 16);
297 MD5Update(&ctx
, b
+ 20, (p
- b
) - 20);
298 MD5Update(&ctx
, radiussecret
, strlen(radiussecret
));
299 MD5Final(hash
, &ctx
);
300 memcpy(b
+ 4, hash
, 16);
301 memcpy(radius
[r
].auth
, hash
, 16);
303 memset(&addr
, 0, sizeof(addr
));
304 addr
.sin_family
= AF_INET
;
305 *(u32
*) & addr
.sin_addr
= htonl(radiusserver
[(radius
[r
].try - 1) % numradiusservers
]);
306 addr
.sin_port
= htons((state
== RADIUSAUTH
) ? RADPORT
: RADAPORT
);
308 log_hex(5, "RADIUS Send", b
, (p
- b
));
309 sendto(radfd
, b
, p
- b
, 0, (void *) &addr
, sizeof(addr
));
312 // process RADIUS response
313 void processrad(u8
* buf
, int len
)
324 STAT(call_processrad
);
326 log_hex(5, "RADIUS Response", buf
, len
);
327 if (len
< 20 || len
< ntohs(*(u16
*) (buf
+ 2)))
329 log(1, 0, 0, 0, "Duff RADIUS response length %d\n", len
);
332 len
= ntohs(*(u16
*) (buf
+ 2));
334 s
= radius
[r
].session
;
335 log(3, 0, s
, session
[s
].tunnel
, "Received %s, radius %d response for session %u\n", radius_states
[radius
[r
].state
], r
, s
);
336 if (!s
&& radius
[r
].state
!= RADIUSSTOP
)
338 log(1, 0, s
, session
[s
].tunnel
, " Unexpected RADIUS response\n");
341 if (radius
[r
].state
!= RADIUSAUTH
&& radius
[r
].state
!= RADIUSSTART
&& radius
[r
].state
!= RADIUSSTOP
)
343 log(1, 0, s
, session
[s
].tunnel
, " Unexpected RADIUS response\n");
346 t
= session
[s
].tunnel
;
348 MD5Update(&ctx
, buf
, 4);
349 MD5Update(&ctx
, radius
[r
].auth
, 16);
350 MD5Update(&ctx
, buf
+ 20, len
- 20);
351 MD5Update(&ctx
, radiussecret
, strlen(radiussecret
));
352 MD5Final(hash
, &ctx
);
354 if (memcmp(hash
, buf
+ 4, 16))
356 log(0, 0, s
, session
[s
].tunnel
, " Incorrect auth on RADIUS response\n");
357 radius
[r
].state
= RADIUSWAIT
;
360 if ((radius
[r
].state
== RADIUSAUTH
&& *buf
!= 2 && *buf
!= 3) ||
361 ((radius
[r
].state
== RADIUSSTART
|| radius
[r
].state
== RADIUSSTOP
) && *buf
!= 5))
363 log(1, 0, s
, session
[s
].tunnel
, " Unexpected RADIUS response %d\n", *buf
);
364 radius
[r
].state
= RADIUSWAIT
;
367 if (radius
[r
].state
== RADIUSAUTH
)
369 log(4, 0, s
, session
[s
].tunnel
, " Original response is \"%s\"\n", (*buf
== 2) ? "accept" : "reject");
370 // process auth response
374 u8
*p
= makeppp(b
, 0, 0, t
, s
, PPPCHAP
);
377 struct param_post_auth packet
= { &tunnel
[t
], &session
[s
], session
[s
].user
, (*buf
== 2), PPPCHAP
};
378 run_plugins(PLUGIN_POST_AUTH
, &packet
);
379 *buf
= packet
.auth_allowed
? 2 : 3;
382 log(3, 0, s
, session
[s
].tunnel
, " CHAP User %s authentication %s.\n", session
[s
].user
,
383 (*buf
== 2) ? "allowed" : "denied");
384 *p
= (*buf
== 2) ? 3 : 4; // ack/nak
386 *(u16
*) (p
+ 2) = ntohs(4); // no message
387 tunnelsend(b
, (p
- b
) + 4, t
); // send it
392 u8
*p
= makeppp(b
, 0, 0, t
, s
, PPPPAP
);
395 struct param_post_auth packet
= { &tunnel
[t
], &session
[s
], session
[s
].user
, (*buf
== 2), PPPPAP
};
396 run_plugins(PLUGIN_POST_AUTH
, &packet
);
397 *buf
= packet
.auth_allowed
? 2 : 3;
400 log(3, 0, s
, session
[s
].tunnel
, " PAP User %s authentication %s.\n", session
[s
].user
,
401 (*buf
== 2) ? "allowed" : "denied");
405 *(u16
*) (p
+ 2) = ntohs(5);
406 p
[4] = 0; // no message
407 tunnelsend(b
, (p
- b
) + 5, t
); // send it
413 // Extract IP, routes, etc
416 for (p
= buf
+ 20; p
< e
&& p
[1]; p
+= p
[1])
420 // Statically assigned address
421 log(3, 0, s
, session
[s
].tunnel
, " Radius reply contains IP address %s\n", inet_toa(*(u32
*) (p
+ 2)));
422 session
[s
].ip
= ntohl(*(u32
*) (p
+ 2));
427 log(3, 0, s
, session
[s
].tunnel
, " Radius reply contains primary DNS address %s\n", inet_toa(ntohl(*(u32
*) (p
+ 2))));
428 session
[s
].dns1
= ntohl(*(u32
*) (p
+ 2));
433 log(3, 0, s
, session
[s
].tunnel
, " Radius reply contains secondary DNS address %s\n", inet_toa(ntohl(*(u32
*) (p
+ 2))));
434 session
[s
].dns2
= ntohl(*(u32
*) (p
+ 2));
439 ipt ip
= 0, mask
= 0;
444 while (n
< e
&& (isdigit(*n
) || *n
== '.'))
452 u
= u
* 10 + *n
- '0';
459 while (n
< e
&& isdigit(*n
))
460 bits
= bits
* 10 + *n
++ - '0';
461 mask
= (( -1) << (32 - bits
));
463 else if ((ip
>> 24) < 128)
465 else if ((ip
>> 24) < 192)
469 if (routes
== MAXROUTE
)
471 log(1, 0, s
, session
[s
].tunnel
, " Too many routes\n");
475 log(3, 0, s
, session
[s
].tunnel
, " Radius reply contains route for %d/%d\n",
478 session
[s
].route
[routes
].ip
= ip
;
479 session
[s
].route
[routes
].mask
= mask
;
485 // Vendor-Specific Attribute
486 int vendor
= ntohl(*(int *)(p
+ 2));
487 char attrib
= *(p
+ 6);
488 char attrib_length
= *(p
+ 7) - 2;
489 log(3, 0, s
, session
[s
].tunnel
, " Radius reply contains Vendor-Specific. Vendor=%d Attrib=%d Length=%d\n", vendor
, attrib
, attrib_length
);
490 if (attrib_length
== 0) continue;
492 log(3, 0, s
, session
[s
].tunnel
, " Unknown vendor-specific\n");
495 char *avpair
, *value
, *key
, *newp
;
496 avpair
= key
= calloc(attrib_length
+ 1, 1);
497 memcpy(avpair
, p
+ 8, attrib_length
);
498 log(3, 0, s
, session
[s
].tunnel
, " Cisco-Avpair value: %s\n", avpair
);
500 value
= strchr(key
, '=');
504 // Trim quotes off reply string
505 if (*value
== '\'' || *value
== '\"')
509 x
= value
+ strlen(value
) - 1;
510 if (*x
== '\'' || *x
== '\"')
515 newp
= strchr(value
, ',');
516 if (newp
) *newp
++ = 0;
518 struct param_radius_response p
= { &tunnel
[session
[s
].tunnel
], &session
[s
], key
, value
};
519 run_plugins(PLUGIN_RADIUS_RESPONSE
, &p
);
530 log(2, 0, s
, session
[s
].tunnel
, " Authentication denied for %s\n", session
[s
].user
);
534 // Check for Assign-IP-Address
535 if (!session
[s
].ip
|| session
[s
].ip
== 0xFFFFFFFE)
537 session
[s
].ip
= assign_ip_address();
539 log(3, 0, s
, t
, " No IP allocated by radius. Assigned %s from pool\n",
540 inet_toa(htonl(session
[s
].ip
)));
542 log(3, 0, s
, t
, " No IP allocated by radius. None available in pool\n");
544 if (!session
[s
].dns1
&& default_dns1
)
546 session
[s
].dns1
= htonl(default_dns1
);
547 log(3, 0, s
, t
, " Sending dns1 = %s\n", inet_toa(default_dns1
));
549 if (!session
[s
].dns2
&& default_dns2
)
551 session
[s
].dns2
= htonl(default_dns2
);
552 log(3, 0, s
, t
, " Sending dns2 = %s\n", inet_toa(default_dns2
));
557 // Valid Session, set it up
559 sessionsetup(t
, s
, routes
);
563 log(0, 0, s
, t
, " End of processrad(), but no valid session exists.\n");
564 sessionkill(s
, "Can't create valid session");
569 log(3, 0, s
, t
, " RADIUS response in state %d\n", radius
[r
].state
);
573 // finished with RADIUS
577 // Send a retry for RADIUS/CHAP message
578 void radiusretry(u8 r
)
580 sessionidt s
= radius
[r
].session
;
583 STAT(call_radiusretry
);
586 t
= session
[s
].tunnel
;
588 switch (radius
[r
].state
)
590 case RADIUSCHAP
: // sending CHAP down PPP
594 sendipcp(t
, s
); // send IPCP
596 case RADIUSAUTH
: // sending auth to RADIUS server
597 radiussend(r
, RADIUSAUTH
);
599 case RADIUSSTART
: // sending start accounting to RADIUS server
600 radiussend(r
, RADIUSSTART
);
602 case RADIUSSTOP
: // sending stop accounting to RADIUS server
603 radiussend(r
, RADIUSSTOP
);
606 case RADIUSNULL
: // Not in use
607 case RADIUSWAIT
: // waiting timeout before available, in case delayed reply from RADIUS server
608 // free up RADIUS task
610 log(3, 0, s
, session
[s
].tunnel
, "Freeing up radius session %d\n", r
);