1972a1bcfSBrian Somers /* 2972a1bcfSBrian Somers * Copyright 1999 Internet Business Solutions Ltd., Switzerland 3972a1bcfSBrian Somers * All rights reserved. 4972a1bcfSBrian Somers * 5972a1bcfSBrian Somers * Redistribution and use in source and binary forms, with or without 6972a1bcfSBrian Somers * modification, are permitted provided that the following conditions 7972a1bcfSBrian Somers * are met: 8972a1bcfSBrian Somers * 1. Redistributions of source code must retain the above copyright 9972a1bcfSBrian Somers * notice, this list of conditions and the following disclaimer. 10972a1bcfSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 11972a1bcfSBrian Somers * notice, this list of conditions and the following disclaimer in the 12972a1bcfSBrian Somers * documentation and/or other materials provided with the distribution. 13972a1bcfSBrian Somers * 14972a1bcfSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15972a1bcfSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16972a1bcfSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17972a1bcfSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18972a1bcfSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19972a1bcfSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20972a1bcfSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21972a1bcfSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22972a1bcfSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23972a1bcfSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24972a1bcfSBrian Somers * SUCH DAMAGE. 25972a1bcfSBrian Somers * 2697d92980SPeter Wemm * $FreeBSD$ 27972a1bcfSBrian Somers * 28972a1bcfSBrian Somers */ 29972a1bcfSBrian Somers 30972a1bcfSBrian Somers #include <sys/param.h> 31972a1bcfSBrian Somers #include <netinet/in_systm.h> 32972a1bcfSBrian Somers #include <netinet/in.h> 33972a1bcfSBrian Somers #include <netinet/ip.h> 34972a1bcfSBrian Somers #include <arpa/inet.h> 35972a1bcfSBrian Somers #include <sys/un.h> 36972a1bcfSBrian Somers 37972a1bcfSBrian Somers #include <errno.h> 38972a1bcfSBrian Somers #include <radlib.h> 39972a1bcfSBrian Somers #include <stdio.h> 40972a1bcfSBrian Somers #include <stdlib.h> 41972a1bcfSBrian Somers #include <string.h> 42f0cdd9c0SBrian Somers #include <sys/time.h> 43972a1bcfSBrian Somers #include <termios.h> 44f10f5203SBrian Somers #include <ttyent.h> 45f10f5203SBrian Somers #include <unistd.h> 46f10f5203SBrian Somers #include <netdb.h> 47972a1bcfSBrian Somers 485d9e6103SBrian Somers #include "layer.h" 49972a1bcfSBrian Somers #include "defs.h" 50972a1bcfSBrian Somers #include "log.h" 51972a1bcfSBrian Somers #include "descriptor.h" 52972a1bcfSBrian Somers #include "prompt.h" 53972a1bcfSBrian Somers #include "timer.h" 54972a1bcfSBrian Somers #include "fsm.h" 55972a1bcfSBrian Somers #include "iplist.h" 56972a1bcfSBrian Somers #include "slcompress.h" 57972a1bcfSBrian Somers #include "throughput.h" 58972a1bcfSBrian Somers #include "lqr.h" 59972a1bcfSBrian Somers #include "hdlc.h" 60972a1bcfSBrian Somers #include "mbuf.h" 61972a1bcfSBrian Somers #include "ipcp.h" 62972a1bcfSBrian Somers #include "route.h" 63972a1bcfSBrian Somers #include "command.h" 64972a1bcfSBrian Somers #include "filter.h" 65972a1bcfSBrian Somers #include "lcp.h" 66972a1bcfSBrian Somers #include "ccp.h" 67972a1bcfSBrian Somers #include "link.h" 68972a1bcfSBrian Somers #include "mp.h" 69972a1bcfSBrian Somers #include "radius.h" 70f0cdd9c0SBrian Somers #include "auth.h" 71f0cdd9c0SBrian Somers #include "async.h" 72f0cdd9c0SBrian Somers #include "physical.h" 73f0cdd9c0SBrian Somers #include "chat.h" 74f0cdd9c0SBrian Somers #include "cbcp.h" 75f0cdd9c0SBrian Somers #include "chap.h" 76f0cdd9c0SBrian Somers #include "datalink.h" 77972a1bcfSBrian Somers #include "bundle.h" 78972a1bcfSBrian Somers 79f0cdd9c0SBrian Somers /* 80f0cdd9c0SBrian Somers * rad_continue_send_request() has given us `got' (non-zero). Deal with it. 81f0cdd9c0SBrian Somers */ 82f0cdd9c0SBrian Somers static void 83f0cdd9c0SBrian Somers radius_Process(struct radius *r, int got) 84972a1bcfSBrian Somers { 85972a1bcfSBrian Somers char *argv[MAXARGS], *nuke; 86f0cdd9c0SBrian Somers struct bundle *bundle; 8728e610e3SBrian Somers int argc, addrs; 8828e610e3SBrian Somers size_t len; 89972a1bcfSBrian Somers struct in_range dest; 90972a1bcfSBrian Somers struct in_addr gw; 91f0cdd9c0SBrian Somers const void *data; 92972a1bcfSBrian Somers 93f0cdd9c0SBrian Somers r->cx.fd = -1; /* Stop select()ing */ 94972a1bcfSBrian Somers 95972a1bcfSBrian Somers switch (got) { 96972a1bcfSBrian Somers case RAD_ACCESS_ACCEPT: 97f0cdd9c0SBrian Somers log_Printf(LogPHASE, "Radius: ACCEPT received\n"); 98972a1bcfSBrian Somers break; 99972a1bcfSBrian Somers 100f0cdd9c0SBrian Somers case RAD_ACCESS_REJECT: 101f0cdd9c0SBrian Somers log_Printf(LogPHASE, "Radius: REJECT received\n"); 102f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 103f0cdd9c0SBrian Somers rad_close(r->cx.rad); 104f0cdd9c0SBrian Somers return; 105f0cdd9c0SBrian Somers 106972a1bcfSBrian Somers case RAD_ACCESS_CHALLENGE: 107972a1bcfSBrian Somers /* we can't deal with this (for now) ! */ 108f0cdd9c0SBrian Somers log_Printf(LogPHASE, "Radius: CHALLENGE received (can't handle yet)\n"); 109f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 110f0cdd9c0SBrian Somers rad_close(r->cx.rad); 111f0cdd9c0SBrian Somers return; 112972a1bcfSBrian Somers 113972a1bcfSBrian Somers case -1: 114f0cdd9c0SBrian Somers log_Printf(LogPHASE, "radius: %s\n", rad_strerror(r->cx.rad)); 115f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 116f0cdd9c0SBrian Somers rad_close(r->cx.rad); 117f0cdd9c0SBrian Somers return; 118972a1bcfSBrian Somers 119972a1bcfSBrian Somers default: 120972a1bcfSBrian Somers log_Printf(LogERROR, "rad_send_request: Failed %d: %s\n", 121f0cdd9c0SBrian Somers got, rad_strerror(r->cx.rad)); 122f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 123f0cdd9c0SBrian Somers rad_close(r->cx.rad); 124f0cdd9c0SBrian Somers return; 125972a1bcfSBrian Somers } 126972a1bcfSBrian Somers 127972a1bcfSBrian Somers /* So we've been accepted ! Let's see what we've got in our reply :-I */ 128972a1bcfSBrian Somers r->ip.s_addr = r->mask.s_addr = INADDR_NONE; 129972a1bcfSBrian Somers r->mtu = 0; 130972a1bcfSBrian Somers r->vj = 0; 131f0cdd9c0SBrian Somers while ((got = rad_get_attr(r->cx.rad, &data, &len)) > 0) { 132972a1bcfSBrian Somers switch (got) { 133972a1bcfSBrian Somers case RAD_FRAMED_IP_ADDRESS: 134972a1bcfSBrian Somers r->ip = rad_cvt_addr(data); 135f0cdd9c0SBrian Somers log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip)); 136972a1bcfSBrian Somers break; 137972a1bcfSBrian Somers 138972a1bcfSBrian Somers case RAD_FRAMED_IP_NETMASK: 139972a1bcfSBrian Somers r->mask = rad_cvt_addr(data); 140f0cdd9c0SBrian Somers log_Printf(LogPHASE, " Netmask %s\n", inet_ntoa(r->mask)); 141972a1bcfSBrian Somers break; 142972a1bcfSBrian Somers 143972a1bcfSBrian Somers case RAD_FRAMED_MTU: 144972a1bcfSBrian Somers r->mtu = rad_cvt_int(data); 145f0cdd9c0SBrian Somers log_Printf(LogPHASE, " MTU %lu\n", r->mtu); 146972a1bcfSBrian Somers break; 147972a1bcfSBrian Somers 148972a1bcfSBrian Somers case RAD_FRAMED_ROUTING: 149972a1bcfSBrian Somers /* Disabled for now - should we automatically set up some filters ? */ 150972a1bcfSBrian Somers /* rad_cvt_int(data); */ 151972a1bcfSBrian Somers /* bit 1 = Send routing packets */ 152972a1bcfSBrian Somers /* bit 2 = Receive routing packets */ 153972a1bcfSBrian Somers break; 154972a1bcfSBrian Somers 155972a1bcfSBrian Somers case RAD_FRAMED_COMPRESSION: 156972a1bcfSBrian Somers r->vj = rad_cvt_int(data) == 1 ? 1 : 0; 157f0cdd9c0SBrian Somers log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis"); 158972a1bcfSBrian Somers break; 159972a1bcfSBrian Somers 160972a1bcfSBrian Somers case RAD_FRAMED_ROUTE: 161972a1bcfSBrian Somers /* 162972a1bcfSBrian Somers * We expect a string of the format ``dest[/bits] gw [metrics]'' 163972a1bcfSBrian Somers * Any specified metrics are ignored. MYADDR and HISADDR are 164972a1bcfSBrian Somers * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same 165972a1bcfSBrian Somers * as ``HISADDR''. 166972a1bcfSBrian Somers */ 167972a1bcfSBrian Somers 168972a1bcfSBrian Somers if ((nuke = rad_cvt_string(data, len)) == NULL) { 169f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 170f0cdd9c0SBrian Somers rad_close(r->cx.rad); 171f0cdd9c0SBrian Somers return; 172972a1bcfSBrian Somers } 173972a1bcfSBrian Somers 174f0cdd9c0SBrian Somers log_Printf(LogPHASE, " Route: %s\n", nuke); 175f0cdd9c0SBrian Somers bundle = r->cx.auth->physical->dl->bundle; 176972a1bcfSBrian Somers dest.ipaddr.s_addr = dest.mask.s_addr = INADDR_ANY; 177972a1bcfSBrian Somers dest.width = 0; 178972a1bcfSBrian Somers argc = command_Interpret(nuke, strlen(nuke), argv); 179c39aa54eSBrian Somers if (argc < 0) 180c39aa54eSBrian Somers log_Printf(LogWARN, "radius: %s: Syntax error\n", 181c39aa54eSBrian Somers argc == 1 ? argv[0] : "\"\""); 182c39aa54eSBrian Somers else if (argc < 2) 183972a1bcfSBrian Somers log_Printf(LogWARN, "radius: %s: Invalid route\n", 184972a1bcfSBrian Somers argc == 1 ? argv[0] : "\"\""); 185972a1bcfSBrian Somers else if ((strcasecmp(argv[0], "default") != 0 && 186972a1bcfSBrian Somers !ParseAddr(&bundle->ncp.ipcp, argv[0], &dest.ipaddr, 187972a1bcfSBrian Somers &dest.mask, &dest.width)) || 188972a1bcfSBrian Somers !ParseAddr(&bundle->ncp.ipcp, argv[1], &gw, NULL, NULL)) 189972a1bcfSBrian Somers log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 190972a1bcfSBrian Somers argv[0], argv[1]); 191972a1bcfSBrian Somers else { 192972a1bcfSBrian Somers if (dest.width == 32 && strchr(argv[0], '/') == NULL) 193972a1bcfSBrian Somers /* No mask specified - use the natural mask */ 194bc76350eSBrian Somers dest.mask = addr2mask(dest.ipaddr); 195972a1bcfSBrian Somers addrs = 0; 196972a1bcfSBrian Somers 197972a1bcfSBrian Somers if (!strncasecmp(argv[0], "HISADDR", 7)) 198972a1bcfSBrian Somers addrs = ROUTE_DSTHISADDR; 199972a1bcfSBrian Somers else if (!strncasecmp(argv[0], "MYADDR", 6)) 200972a1bcfSBrian Somers addrs = ROUTE_DSTMYADDR; 201972a1bcfSBrian Somers 202972a1bcfSBrian Somers if (gw.s_addr == INADDR_ANY) { 203972a1bcfSBrian Somers addrs |= ROUTE_GWHISADDR; 204972a1bcfSBrian Somers gw = bundle->ncp.ipcp.peer_ip; 205972a1bcfSBrian Somers } else if (strcasecmp(argv[1], "HISADDR") == 0) 206972a1bcfSBrian Somers addrs |= ROUTE_GWHISADDR; 207972a1bcfSBrian Somers 208972a1bcfSBrian Somers route_Add(&r->routes, addrs, dest.ipaddr, dest.mask, gw); 209972a1bcfSBrian Somers } 210972a1bcfSBrian Somers free(nuke); 211972a1bcfSBrian Somers break; 212972a1bcfSBrian Somers } 213972a1bcfSBrian Somers } 214972a1bcfSBrian Somers 215972a1bcfSBrian Somers if (got == -1) { 216f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n", 217f0cdd9c0SBrian Somers rad_strerror(r->cx.rad)); 218f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 219f0cdd9c0SBrian Somers rad_close(r->cx.rad); 220f0cdd9c0SBrian Somers } else { 221f0cdd9c0SBrian Somers r->valid = 1; 222f0cdd9c0SBrian Somers auth_Success(r->cx.auth); 223f0cdd9c0SBrian Somers rad_close(r->cx.rad); 224f0cdd9c0SBrian Somers } 225972a1bcfSBrian Somers } 226972a1bcfSBrian Somers 227f0cdd9c0SBrian Somers /* 228f013f33eSBrian Somers * We've either timed out or select()ed on the read fdescriptor 229f0cdd9c0SBrian Somers */ 230f0cdd9c0SBrian Somers static void 231f0cdd9c0SBrian Somers radius_Continue(struct radius *r, int sel) 232f0cdd9c0SBrian Somers { 233f0cdd9c0SBrian Somers struct timeval tv; 234f0cdd9c0SBrian Somers int got; 235972a1bcfSBrian Somers 236f0cdd9c0SBrian Somers timer_Stop(&r->cx.timer); 237f0cdd9c0SBrian Somers if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) { 238f0cdd9c0SBrian Somers log_Printf(LogPHASE, "Radius: Request re-sent\n"); 239f0cdd9c0SBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 240f0cdd9c0SBrian Somers timer_Start(&r->cx.timer); 241f0cdd9c0SBrian Somers return; 242f0cdd9c0SBrian Somers } 243f0cdd9c0SBrian Somers 244f0cdd9c0SBrian Somers radius_Process(r, got); 245f0cdd9c0SBrian Somers } 246f0cdd9c0SBrian Somers 247f0cdd9c0SBrian Somers /* 248f0cdd9c0SBrian Somers * Time to call rad_continue_send_request() - timed out. 249f0cdd9c0SBrian Somers */ 250f0cdd9c0SBrian Somers static void 251f0cdd9c0SBrian Somers radius_Timeout(void *v) 252f0cdd9c0SBrian Somers { 253f0cdd9c0SBrian Somers radius_Continue((struct radius *)v, 0); 254f0cdd9c0SBrian Somers } 255f0cdd9c0SBrian Somers 256f0cdd9c0SBrian Somers /* 257f0cdd9c0SBrian Somers * Time to call rad_continue_send_request() - something to read. 258f0cdd9c0SBrian Somers */ 259f0cdd9c0SBrian Somers static void 260f013f33eSBrian Somers radius_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 261f0cdd9c0SBrian Somers { 262f0cdd9c0SBrian Somers radius_Continue(descriptor2radius(d), 1); 263f0cdd9c0SBrian Somers } 264f0cdd9c0SBrian Somers 265f0cdd9c0SBrian Somers /* 266f013f33eSBrian Somers * Behave as a struct fdescriptor (fdescriptor.h) 267f0cdd9c0SBrian Somers */ 268f0cdd9c0SBrian Somers static int 269f013f33eSBrian Somers radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 270f0cdd9c0SBrian Somers { 271f0cdd9c0SBrian Somers struct radius *rad = descriptor2radius(d); 272f0cdd9c0SBrian Somers 273f0cdd9c0SBrian Somers if (r && rad->cx.fd != -1) { 274f0cdd9c0SBrian Somers FD_SET(rad->cx.fd, r); 275f0cdd9c0SBrian Somers if (*n < rad->cx.fd + 1) 276f0cdd9c0SBrian Somers *n = rad->cx.fd + 1; 277f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd); 27882d6780cSBrian Somers return 1; 279972a1bcfSBrian Somers } 280972a1bcfSBrian Somers 281f0cdd9c0SBrian Somers return 0; 282f0cdd9c0SBrian Somers } 283f0cdd9c0SBrian Somers 284f0cdd9c0SBrian Somers /* 285f013f33eSBrian Somers * Behave as a struct fdescriptor (fdescriptor.h) 286f0cdd9c0SBrian Somers */ 287f0cdd9c0SBrian Somers static int 288f013f33eSBrian Somers radius_IsSet(struct fdescriptor *d, const fd_set *fdset) 289f0cdd9c0SBrian Somers { 290f0cdd9c0SBrian Somers struct radius *r = descriptor2radius(d); 291f0cdd9c0SBrian Somers 292f0cdd9c0SBrian Somers return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset); 293f0cdd9c0SBrian Somers } 294f0cdd9c0SBrian Somers 295f0cdd9c0SBrian Somers /* 296f013f33eSBrian Somers * Behave as a struct fdescriptor (fdescriptor.h) 297f0cdd9c0SBrian Somers */ 298f0cdd9c0SBrian Somers static int 299f013f33eSBrian Somers radius_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 300f0cdd9c0SBrian Somers { 301f0cdd9c0SBrian Somers /* We never want to write here ! */ 302f0cdd9c0SBrian Somers log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n"); 303f0cdd9c0SBrian Somers return 0; 304f0cdd9c0SBrian Somers } 305f0cdd9c0SBrian Somers 306f0cdd9c0SBrian Somers /* 307f0cdd9c0SBrian Somers * Initialise ourselves 308f0cdd9c0SBrian Somers */ 309f0cdd9c0SBrian Somers void 310f0cdd9c0SBrian Somers radius_Init(struct radius *r) 311f0cdd9c0SBrian Somers { 312f0cdd9c0SBrian Somers r->valid = 0; 313f0cdd9c0SBrian Somers r->cx.fd = -1; 314f0cdd9c0SBrian Somers *r->cfg.file = '\0';; 315f0cdd9c0SBrian Somers r->desc.type = RADIUS_DESCRIPTOR; 316f0cdd9c0SBrian Somers r->desc.UpdateSet = radius_UpdateSet; 317f0cdd9c0SBrian Somers r->desc.IsSet = radius_IsSet; 318f0cdd9c0SBrian Somers r->desc.Read = radius_Read; 319f0cdd9c0SBrian Somers r->desc.Write = radius_Write; 320f0cdd9c0SBrian Somers memset(&r->cx.timer, '\0', sizeof r->cx.timer); 321f0cdd9c0SBrian Somers } 322f0cdd9c0SBrian Somers 323f0cdd9c0SBrian Somers /* 324f0cdd9c0SBrian Somers * Forget everything and go back to initialised state. 325f0cdd9c0SBrian Somers */ 326f0cdd9c0SBrian Somers void 327f0cdd9c0SBrian Somers radius_Destroy(struct radius *r) 328f0cdd9c0SBrian Somers { 329f0cdd9c0SBrian Somers r->valid = 0; 330f0cdd9c0SBrian Somers timer_Stop(&r->cx.timer); 331f0cdd9c0SBrian Somers route_DeleteAll(&r->routes); 332f0cdd9c0SBrian Somers if (r->cx.fd != -1) { 333f0cdd9c0SBrian Somers r->cx.fd = -1; 334f0cdd9c0SBrian Somers rad_close(r->cx.rad); 335f0cdd9c0SBrian Somers } 336f0cdd9c0SBrian Somers } 337f0cdd9c0SBrian Somers 338f0cdd9c0SBrian Somers /* 339f0cdd9c0SBrian Somers * Start an authentication request to the RADIUS server. 340f0cdd9c0SBrian Somers */ 341f0cdd9c0SBrian Somers void 342f0cdd9c0SBrian Somers radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, 343f0cdd9c0SBrian Somers const char *key, const char *challenge) 344f0cdd9c0SBrian Somers { 345f10f5203SBrian Somers struct ttyent *ttyp; 346f0cdd9c0SBrian Somers struct timeval tv; 347f10f5203SBrian Somers int got, slot; 348f10f5203SBrian Somers char hostname[MAXHOSTNAMELEN]; 349f10f5203SBrian Somers struct hostent *hp; 350f10f5203SBrian Somers struct in_addr hostaddr; 351f0cdd9c0SBrian Somers 352f0cdd9c0SBrian Somers if (!*r->cfg.file) 353f0cdd9c0SBrian Somers return; 354f0cdd9c0SBrian Somers 355f0cdd9c0SBrian Somers if (r->cx.fd != -1) 356f0cdd9c0SBrian Somers /* 357f0cdd9c0SBrian Somers * We assume that our name/key/challenge is the same as last time, 358f0cdd9c0SBrian Somers * and just continue to wait for the RADIUS server(s). 359f0cdd9c0SBrian Somers */ 360f0cdd9c0SBrian Somers return; 361f0cdd9c0SBrian Somers 362f0cdd9c0SBrian Somers radius_Destroy(r); 363f0cdd9c0SBrian Somers 364f0cdd9c0SBrian Somers if ((r->cx.rad = rad_open()) == NULL) { 365f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_open: %s\n", strerror(errno)); 366f0cdd9c0SBrian Somers return; 367f0cdd9c0SBrian Somers } 368f0cdd9c0SBrian Somers 369f0cdd9c0SBrian Somers if (rad_config(r->cx.rad, r->cfg.file) != 0) { 370f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 371f0cdd9c0SBrian Somers rad_close(r->cx.rad); 372f0cdd9c0SBrian Somers return; 373f0cdd9c0SBrian Somers } 374f0cdd9c0SBrian Somers 375f0cdd9c0SBrian Somers if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) { 376f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 377f0cdd9c0SBrian Somers rad_close(r->cx.rad); 378f0cdd9c0SBrian Somers return; 379f0cdd9c0SBrian Somers } 380f0cdd9c0SBrian Somers 381f0cdd9c0SBrian Somers if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 || 382f0cdd9c0SBrian Somers rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 383f0cdd9c0SBrian Somers rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 384f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 385f0cdd9c0SBrian Somers rad_close(r->cx.rad); 386f0cdd9c0SBrian Somers return; 387f0cdd9c0SBrian Somers } 388f0cdd9c0SBrian Somers 389f0cdd9c0SBrian Somers if (challenge != NULL) { 390f0cdd9c0SBrian Somers /* We're talking CHAP */ 391f0cdd9c0SBrian Somers if (rad_put_string(r->cx.rad, RAD_CHAP_PASSWORD, key) != 0 || 392f0cdd9c0SBrian Somers rad_put_string(r->cx.rad, RAD_CHAP_CHALLENGE, challenge) != 0) { 393f0cdd9c0SBrian Somers log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", 394f0cdd9c0SBrian Somers rad_strerror(r->cx.rad)); 395f0cdd9c0SBrian Somers rad_close(r->cx.rad); 396f0cdd9c0SBrian Somers return; 397f0cdd9c0SBrian Somers } 398f0cdd9c0SBrian Somers } else if (rad_put_string(r->cx.rad, RAD_USER_PASSWORD, key) != 0) { 399f0cdd9c0SBrian Somers /* We're talking PAP */ 400f0cdd9c0SBrian Somers log_Printf(LogERROR, "PAP: rad_put_string: %s\n", rad_strerror(r->cx.rad)); 401f0cdd9c0SBrian Somers rad_close(r->cx.rad); 402f0cdd9c0SBrian Somers return; 403f0cdd9c0SBrian Somers } 404f0cdd9c0SBrian Somers 405f10f5203SBrian Somers if (gethostname(hostname, sizeof hostname) != 0) 406f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 407f10f5203SBrian Somers else { 408f10f5203SBrian Somers if ((hp = gethostbyname(hostname)) != NULL) { 409f10f5203SBrian Somers hostaddr.s_addr = *(u_long *)hp->h_addr; 410f10f5203SBrian Somers if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 411f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 412f10f5203SBrian Somers rad_strerror(r->cx.rad)); 413f10f5203SBrian Somers rad_close(r->cx.rad); 414f10f5203SBrian Somers return; 415f10f5203SBrian Somers } 416f10f5203SBrian Somers } 417f10f5203SBrian Somers if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 418f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 419f10f5203SBrian Somers rad_strerror(r->cx.rad)); 420f10f5203SBrian Somers rad_close(r->cx.rad); 421f10f5203SBrian Somers return; 422f10f5203SBrian Somers } 423f10f5203SBrian Somers } 424f10f5203SBrian Somers 425f10f5203SBrian Somers if (authp->physical->handler && 426f10f5203SBrian Somers authp->physical->handler->type == TTY_DEVICE) { 427f10f5203SBrian Somers setttyent(); 428f10f5203SBrian Somers for (slot = 1; (ttyp = getttyent()); ++slot) 429f10f5203SBrian Somers if (!strcmp(ttyp->ty_name, authp->physical->name.base)) { 430f10f5203SBrian Somers if(rad_put_int(r->cx.rad, RAD_NAS_PORT, slot) != 0) { 431f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 432f10f5203SBrian Somers rad_strerror(r->cx.rad)); 433f10f5203SBrian Somers rad_close(r->cx.rad); 434f10f5203SBrian Somers endttyent(); 435f10f5203SBrian Somers return; 436f10f5203SBrian Somers } 437f10f5203SBrian Somers break; 438f10f5203SBrian Somers } 439f10f5203SBrian Somers endttyent(); 440f10f5203SBrian Somers } 441f10f5203SBrian Somers 442f10f5203SBrian Somers 443f0cdd9c0SBrian Somers if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 444f0cdd9c0SBrian Somers radius_Process(r, got); 445f0cdd9c0SBrian Somers else { 446f0cdd9c0SBrian Somers log_Printf(LogPHASE, "Radius: Request sent\n"); 447f0cdd9c0SBrian Somers log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 448f0cdd9c0SBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 449f0cdd9c0SBrian Somers r->cx.timer.func = radius_Timeout; 450f0cdd9c0SBrian Somers r->cx.timer.name = "radius"; 451f0cdd9c0SBrian Somers r->cx.timer.arg = r; 452f0cdd9c0SBrian Somers r->cx.auth = authp; 453f0cdd9c0SBrian Somers timer_Start(&r->cx.timer); 454f0cdd9c0SBrian Somers } 455f0cdd9c0SBrian Somers } 456f0cdd9c0SBrian Somers 457f0cdd9c0SBrian Somers /* 458f0cdd9c0SBrian Somers * How do things look at the moment ? 459f0cdd9c0SBrian Somers */ 460972a1bcfSBrian Somers void 461972a1bcfSBrian Somers radius_Show(struct radius *r, struct prompt *p) 462972a1bcfSBrian Somers { 463972a1bcfSBrian Somers prompt_Printf(p, " Radius config: %s", *r->cfg.file ? r->cfg.file : "none"); 464972a1bcfSBrian Somers if (r->valid) { 465972a1bcfSBrian Somers prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip)); 466972a1bcfSBrian Somers prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask)); 467972a1bcfSBrian Somers prompt_Printf(p, " MTU: %lu\n", r->mtu); 468972a1bcfSBrian Somers prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis"); 469972a1bcfSBrian Somers if (r->routes) 470972a1bcfSBrian Somers route_ShowSticky(p, r->routes, " Routes", 16); 471972a1bcfSBrian Somers } else 472972a1bcfSBrian Somers prompt_Printf(p, " (not authenticated)\n"); 473972a1bcfSBrian Somers } 474