2 * Copyright 1999 Internet Business Solutions Ltd., Switzerland
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
30 #include <sys/param.h>
31 #include <sys/socket.h>
32 #include <netinet/in_systm.h>
33 #include <netinet/in.h>
34 #include <netinet/ip.h>
35 #include <arpa/inet.h>
37 #include <net/route.h>
58 #include "descriptor.h"
63 #include "slcompress.h"
64 #include "throughput.h"
87 * rad_continue_send_request() has given us `got' (non-zero). Deal with it.
90 radius_Process(struct radius *r, int got)
92 char *argv[MAXARGS], *nuke;
93 struct bundle *bundle;
100 r->cx.fd = -1; /* Stop select()ing */
103 case RAD_ACCESS_ACCEPT:
104 log_Printf(LogPHASE, "Radius: ACCEPT received\n");
107 case RAD_ACCESS_REJECT:
108 log_Printf(LogPHASE, "Radius: REJECT received\n");
109 auth_Failure(r->cx.auth);
110 rad_close(r->cx.rad);
113 case RAD_ACCESS_CHALLENGE:
114 /* we can't deal with this (for now) ! */
115 log_Printf(LogPHASE, "Radius: CHALLENGE received (can't handle yet)\n");
116 auth_Failure(r->cx.auth);
117 rad_close(r->cx.rad);
121 log_Printf(LogPHASE, "radius: %s\n", rad_strerror(r->cx.rad));
122 auth_Failure(r->cx.auth);
123 rad_close(r->cx.rad);
127 log_Printf(LogERROR, "rad_send_request: Failed %d: %s\n",
128 got, rad_strerror(r->cx.rad));
129 auth_Failure(r->cx.auth);
130 rad_close(r->cx.rad);
134 /* So we've been accepted ! Let's see what we've got in our reply :-I */
135 r->ip.s_addr = r->mask.s_addr = INADDR_NONE;
138 while ((got = rad_get_attr(r->cx.rad, &data, &len)) > 0) {
140 case RAD_FRAMED_IP_ADDRESS:
141 r->ip = rad_cvt_addr(data);
142 log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip));
145 case RAD_FRAMED_IP_NETMASK:
146 r->mask = rad_cvt_addr(data);
147 log_Printf(LogPHASE, " Netmask %s\n", inet_ntoa(r->mask));
151 r->mtu = rad_cvt_int(data);
152 log_Printf(LogPHASE, " MTU %lu\n", r->mtu);
155 case RAD_FRAMED_ROUTING:
156 /* Disabled for now - should we automatically set up some filters ? */
157 /* rad_cvt_int(data); */
158 /* bit 1 = Send routing packets */
159 /* bit 2 = Receive routing packets */
162 case RAD_FRAMED_COMPRESSION:
163 r->vj = rad_cvt_int(data) == 1 ? 1 : 0;
164 log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis");
167 case RAD_FRAMED_ROUTE:
169 * We expect a string of the format ``dest[/bits] gw [metrics]''
170 * Any specified metrics are ignored. MYADDR and HISADDR are
171 * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same
175 if ((nuke = rad_cvt_string(data, len)) == NULL) {
176 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
177 rad_close(r->cx.rad);
181 log_Printf(LogPHASE, " Route: %s\n", nuke);
182 bundle = r->cx.auth->physical->dl->bundle;
183 dest.ipaddr.s_addr = dest.mask.s_addr = INADDR_ANY;
185 argc = command_Interpret(nuke, strlen(nuke), argv);
187 log_Printf(LogWARN, "radius: %s: Syntax error\n",
188 argc == 1 ? argv[0] : "\"\"");
190 log_Printf(LogWARN, "radius: %s: Invalid route\n",
191 argc == 1 ? argv[0] : "\"\"");
192 else if ((strcasecmp(argv[0], "default") != 0 &&
193 !ParseAddr(&bundle->ncp.ipcp, argv[0], &dest.ipaddr,
194 &dest.mask, &dest.width)) ||
195 !ParseAddr(&bundle->ncp.ipcp, argv[1], &gw, NULL, NULL))
196 log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
199 if (dest.width == 32 && strchr(argv[0], '/') == NULL)
200 /* No mask specified - use the natural mask */
201 dest.mask = addr2mask(dest.ipaddr);
204 if (!strncasecmp(argv[0], "HISADDR", 7))
205 addrs = ROUTE_DSTHISADDR;
206 else if (!strncasecmp(argv[0], "MYADDR", 6))
207 addrs = ROUTE_DSTMYADDR;
209 if (gw.s_addr == INADDR_ANY) {
210 addrs |= ROUTE_GWHISADDR;
211 gw = bundle->ncp.ipcp.peer_ip;
212 } else if (strcasecmp(argv[1], "HISADDR") == 0)
213 addrs |= ROUTE_GWHISADDR;
215 route_Add(&r->routes, addrs, dest.ipaddr, dest.mask, gw);
223 log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n",
224 rad_strerror(r->cx.rad));
225 auth_Failure(r->cx.auth);
226 rad_close(r->cx.rad);
229 auth_Success(r->cx.auth);
230 rad_close(r->cx.rad);
235 * We've either timed out or select()ed on the read descriptor
238 radius_Continue(struct radius *r, int sel)
243 timer_Stop(&r->cx.timer);
244 if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) {
245 log_Printf(LogPHASE, "Radius: Request re-sent\n");
246 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
247 timer_Start(&r->cx.timer);
251 radius_Process(r, got);
255 * Time to call rad_continue_send_request() - timed out.
258 radius_Timeout(void *v)
260 radius_Continue((struct radius *)v, 0);
264 * Time to call rad_continue_send_request() - something to read.
267 radius_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
269 radius_Continue(descriptor2radius(d), 1);
273 * Behave as a struct fdescriptor (descriptor.h)
276 radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
278 struct radius *rad = descriptor2radius(d);
280 if (r && rad->cx.fd != -1) {
281 FD_SET(rad->cx.fd, r);
282 if (*n < rad->cx.fd + 1)
284 log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd);
292 * Behave as a struct fdescriptor (descriptor.h)
295 radius_IsSet(struct fdescriptor *d, const fd_set *fdset)
297 struct radius *r = descriptor2radius(d);
299 return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset);
303 * Behave as a struct fdescriptor (descriptor.h)
306 radius_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
308 /* We never want to write here ! */
309 log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n");
314 * Initialise ourselves
317 radius_Init(struct radius *r)
321 *r->cfg.file = '\0';;
322 r->desc.type = RADIUS_DESCRIPTOR;
323 r->desc.UpdateSet = radius_UpdateSet;
324 r->desc.IsSet = radius_IsSet;
325 r->desc.Read = radius_Read;
326 r->desc.Write = radius_Write;
327 memset(&r->cx.timer, '\0', sizeof r->cx.timer);
331 * Forget everything and go back to initialised state.
334 radius_Destroy(struct radius *r)
337 timer_Stop(&r->cx.timer);
338 route_DeleteAll(&r->routes);
339 if (r->cx.fd != -1) {
341 rad_close(r->cx.rad);
346 * Start an authentication request to the RADIUS server.
349 radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
350 const char *key, const char *challenge)
355 char hostname[MAXHOSTNAMELEN];
357 struct in_addr hostaddr;
364 * We assume that our name/key/challenge is the same as last time,
365 * and just continue to wait for the RADIUS server(s).
371 if ((r->cx.rad = rad_open()) == NULL) {
372 log_Printf(LogERROR, "rad_open: %s\n", strerror(errno));
376 if (rad_config(r->cx.rad, r->cfg.file) != 0) {
377 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
378 rad_close(r->cx.rad);
382 if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) {
383 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
384 rad_close(r->cx.rad);
388 if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 ||
389 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
390 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) {
391 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
392 rad_close(r->cx.rad);
396 if (challenge != NULL) {
397 /* We're talking CHAP */
398 if (rad_put_string(r->cx.rad, RAD_CHAP_PASSWORD, key) != 0 ||
399 rad_put_string(r->cx.rad, RAD_CHAP_CHALLENGE, challenge) != 0) {
400 log_Printf(LogERROR, "CHAP: rad_put_string: %s\n",
401 rad_strerror(r->cx.rad));
402 rad_close(r->cx.rad);
405 } else if (rad_put_string(r->cx.rad, RAD_USER_PASSWORD, key) != 0) {
406 /* We're talking PAP */
407 log_Printf(LogERROR, "PAP: rad_put_string: %s\n", rad_strerror(r->cx.rad));
408 rad_close(r->cx.rad);
412 if (gethostname(hostname, sizeof hostname) != 0)
413 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
415 if ((hp = gethostbyname(hostname)) != NULL) {
416 hostaddr.s_addr = *(u_long *)hp->h_addr;
417 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
418 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
419 rad_strerror(r->cx.rad));
420 rad_close(r->cx.rad);
424 if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
425 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
426 rad_strerror(r->cx.rad));
427 rad_close(r->cx.rad);
432 if (authp->physical->handler &&
433 authp->physical->handler->type == TTY_DEVICE) {
435 for (slot = 1; (ttyp = getttyent()); ++slot)
436 if (!strcmp(ttyp->ty_name, authp->physical->name.base)) {
437 if(rad_put_int(r->cx.rad, RAD_NAS_PORT, slot) != 0) {
438 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
439 rad_strerror(r->cx.rad));
440 rad_close(r->cx.rad);
450 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
451 radius_Process(r, got);
453 log_Printf(LogPHASE, "Radius: Request sent\n");
454 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
455 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
456 r->cx.timer.func = radius_Timeout;
457 r->cx.timer.name = "radius";
460 timer_Start(&r->cx.timer);
465 * How do things look at the moment ?
468 radius_Show(struct radius *r, struct prompt *p)
470 prompt_Printf(p, " Radius config: %s", *r->cfg.file ? r->cfg.file : "none");
472 prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip));
473 prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask));
474 prompt_Printf(p, " MTU: %lu\n", r->mtu);
475 prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis");
477 route_ShowSticky(p, r->routes, " Routes", 16);
479 prompt_Printf(p, " (not authenticated)\n");