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 30dfb3194aSDiomidis Spinellis #include <stdint.h> 31972a1bcfSBrian Somers #include <sys/param.h> 328fb5ef5aSBrian Somers 336b457978SBrian Somers #include <sys/socket.h> 34972a1bcfSBrian Somers #include <netinet/in_systm.h> 35972a1bcfSBrian Somers #include <netinet/in.h> 36972a1bcfSBrian Somers #include <netinet/ip.h> 37972a1bcfSBrian Somers #include <arpa/inet.h> 38972a1bcfSBrian Somers #include <sys/un.h> 396b457978SBrian Somers #include <net/route.h> 40972a1bcfSBrian Somers 4110e629b9SBrian Somers #ifdef LOCALRAD 4210e629b9SBrian Somers #include "radlib.h" 43ff8e577bSBrian Somers #include "radlib_vs.h" 4410e629b9SBrian Somers #else 45972a1bcfSBrian Somers #include <radlib.h> 46ff8e577bSBrian Somers #include <radlib_vs.h> 4710e629b9SBrian Somers #endif 4810e629b9SBrian Somers 4910e629b9SBrian Somers #include <errno.h> 508fb5ef5aSBrian Somers #ifndef NODES 518fb5ef5aSBrian Somers #include <md5.h> 528fb5ef5aSBrian Somers #endif 536eafd353SBrian Somers #include <stdarg.h> 54972a1bcfSBrian Somers #include <stdio.h> 55972a1bcfSBrian Somers #include <stdlib.h> 56972a1bcfSBrian Somers #include <string.h> 57f0cdd9c0SBrian Somers #include <sys/time.h> 58972a1bcfSBrian Somers #include <termios.h> 59f10f5203SBrian Somers #include <unistd.h> 60f10f5203SBrian Somers #include <netdb.h> 61972a1bcfSBrian Somers 625d9e6103SBrian Somers #include "layer.h" 63972a1bcfSBrian Somers #include "defs.h" 64972a1bcfSBrian Somers #include "log.h" 65972a1bcfSBrian Somers #include "descriptor.h" 66972a1bcfSBrian Somers #include "prompt.h" 67972a1bcfSBrian Somers #include "timer.h" 68972a1bcfSBrian Somers #include "fsm.h" 69972a1bcfSBrian Somers #include "iplist.h" 70972a1bcfSBrian Somers #include "slcompress.h" 71972a1bcfSBrian Somers #include "throughput.h" 72972a1bcfSBrian Somers #include "lqr.h" 73972a1bcfSBrian Somers #include "hdlc.h" 74972a1bcfSBrian Somers #include "mbuf.h" 7530949fd4SBrian Somers #include "ncpaddr.h" 7630949fd4SBrian Somers #include "ip.h" 77972a1bcfSBrian Somers #include "ipcp.h" 7830949fd4SBrian Somers #include "ipv6cp.h" 79972a1bcfSBrian Somers #include "route.h" 80972a1bcfSBrian Somers #include "command.h" 81972a1bcfSBrian Somers #include "filter.h" 82972a1bcfSBrian Somers #include "lcp.h" 83972a1bcfSBrian Somers #include "ccp.h" 84972a1bcfSBrian Somers #include "link.h" 85972a1bcfSBrian Somers #include "mp.h" 86972a1bcfSBrian Somers #include "radius.h" 87f0cdd9c0SBrian Somers #include "auth.h" 88f0cdd9c0SBrian Somers #include "async.h" 89f0cdd9c0SBrian Somers #include "physical.h" 90f0cdd9c0SBrian Somers #include "chat.h" 91f0cdd9c0SBrian Somers #include "cbcp.h" 92f0cdd9c0SBrian Somers #include "chap.h" 93f0cdd9c0SBrian Somers #include "datalink.h" 9430949fd4SBrian Somers #include "ncp.h" 95972a1bcfSBrian Somers #include "bundle.h" 96ff8e577bSBrian Somers #include "proto.h" 97ff8e577bSBrian Somers 98ff8e577bSBrian Somers #ifndef NODES 99a16061b2SBrian Somers struct mschap_response { 100ff8e577bSBrian Somers u_char ident; 101ff8e577bSBrian Somers u_char flags; 102ff8e577bSBrian Somers u_char lm_response[24]; 103ff8e577bSBrian Somers u_char nt_response[24]; 104ff8e577bSBrian Somers }; 105a16061b2SBrian Somers 106a16061b2SBrian Somers struct mschap2_response { 107a16061b2SBrian Somers u_char ident; 108a16061b2SBrian Somers u_char flags; 109a16061b2SBrian Somers u_char pchallenge[16]; 110a16061b2SBrian Somers u_char reserved[8]; 111a16061b2SBrian Somers u_char response[24]; 112a16061b2SBrian Somers }; 1138fb5ef5aSBrian Somers 1148fb5ef5aSBrian Somers #define AUTH_LEN 16 1158fb5ef5aSBrian Somers #define SALT_LEN 2 1168fb5ef5aSBrian Somers #endif 1178fb5ef5aSBrian Somers 1188fb5ef5aSBrian Somers static const char * 1198fb5ef5aSBrian Somers radius_policyname(int policy) 1208fb5ef5aSBrian Somers { 1218fb5ef5aSBrian Somers switch(policy) { 1228fb5ef5aSBrian Somers case MPPE_POLICY_ALLOWED: 1238fb5ef5aSBrian Somers return "Allowed"; 1248fb5ef5aSBrian Somers case MPPE_POLICY_REQUIRED: 1258fb5ef5aSBrian Somers return "Required"; 1268fb5ef5aSBrian Somers } 1278fb5ef5aSBrian Somers return NumStr(policy, NULL, 0); 1288fb5ef5aSBrian Somers } 1298fb5ef5aSBrian Somers 1308fb5ef5aSBrian Somers static const char * 1318fb5ef5aSBrian Somers radius_typesname(int types) 1328fb5ef5aSBrian Somers { 1338fb5ef5aSBrian Somers switch(types) { 1348fb5ef5aSBrian Somers case MPPE_TYPE_40BIT: 1358fb5ef5aSBrian Somers return "40 bit"; 1368fb5ef5aSBrian Somers case MPPE_TYPE_128BIT: 1378fb5ef5aSBrian Somers return "128 bit"; 1388fb5ef5aSBrian Somers case MPPE_TYPE_40BIT|MPPE_TYPE_128BIT: 1398fb5ef5aSBrian Somers return "40 or 128 bit"; 1408fb5ef5aSBrian Somers } 1418fb5ef5aSBrian Somers return NumStr(types, NULL, 0); 1428fb5ef5aSBrian Somers } 1438fb5ef5aSBrian Somers 1448fb5ef5aSBrian Somers #ifndef NODES 1458fb5ef5aSBrian Somers static void 1468fb5ef5aSBrian Somers demangle(struct radius *r, const void *mangled, size_t mlen, 1478fb5ef5aSBrian Somers char **buf, size_t *len) 1488fb5ef5aSBrian Somers { 1498fb5ef5aSBrian Somers char R[AUTH_LEN]; /* variable names as per rfc2548 */ 1508fb5ef5aSBrian Somers const char *S; 1518fb5ef5aSBrian Somers u_char b[16]; 1528fb5ef5aSBrian Somers const u_char *A, *C; 1538fb5ef5aSBrian Somers MD5_CTX Context; 1548fb5ef5aSBrian Somers int Slen, i, Clen, Ppos; 1558fb5ef5aSBrian Somers u_char *P; 1568fb5ef5aSBrian Somers 1578fb5ef5aSBrian Somers if (mlen % 16 != SALT_LEN) { 1588fb5ef5aSBrian Somers log_Printf(LogWARN, "Cannot interpret mangled data of length %ld\n", 1598fb5ef5aSBrian Somers (u_long)mlen); 1608fb5ef5aSBrian Somers *buf = NULL; 1618fb5ef5aSBrian Somers *len = 0; 1628fb5ef5aSBrian Somers return; 1638fb5ef5aSBrian Somers } 1648fb5ef5aSBrian Somers 1658fb5ef5aSBrian Somers /* We need the RADIUS Request-Authenticator */ 1668fb5ef5aSBrian Somers if (rad_request_authenticator(r->cx.rad, R, sizeof R) != AUTH_LEN) { 1678fb5ef5aSBrian Somers log_Printf(LogWARN, "Cannot obtain the RADIUS request authenticator\n"); 1688fb5ef5aSBrian Somers *buf = NULL; 1698fb5ef5aSBrian Somers *len = 0; 1708fb5ef5aSBrian Somers return; 1718fb5ef5aSBrian Somers } 1728fb5ef5aSBrian Somers 1738fb5ef5aSBrian Somers A = (const u_char *)mangled; /* Salt comes first */ 1748fb5ef5aSBrian Somers C = (const u_char *)mangled + SALT_LEN; /* Then the ciphertext */ 1758fb5ef5aSBrian Somers Clen = mlen - SALT_LEN; 1768fb5ef5aSBrian Somers S = rad_server_secret(r->cx.rad); /* We need the RADIUS secret */ 1778fb5ef5aSBrian Somers Slen = strlen(S); 1788fb5ef5aSBrian Somers P = alloca(Clen); /* We derive our plaintext */ 1798fb5ef5aSBrian Somers 1808fb5ef5aSBrian Somers MD5Init(&Context); 1818fb5ef5aSBrian Somers MD5Update(&Context, S, Slen); 1828fb5ef5aSBrian Somers MD5Update(&Context, R, AUTH_LEN); 1838fb5ef5aSBrian Somers MD5Update(&Context, A, SALT_LEN); 1848fb5ef5aSBrian Somers MD5Final(b, &Context); 1858fb5ef5aSBrian Somers Ppos = 0; 1868fb5ef5aSBrian Somers 1878fb5ef5aSBrian Somers while (Clen) { 1888fb5ef5aSBrian Somers Clen -= 16; 1898fb5ef5aSBrian Somers 1908fb5ef5aSBrian Somers for (i = 0; i < 16; i++) 1918fb5ef5aSBrian Somers P[Ppos++] = C[i] ^ b[i]; 1928fb5ef5aSBrian Somers 1938fb5ef5aSBrian Somers if (Clen) { 1948fb5ef5aSBrian Somers MD5Init(&Context); 1958fb5ef5aSBrian Somers MD5Update(&Context, S, Slen); 1968fb5ef5aSBrian Somers MD5Update(&Context, C, 16); 1978fb5ef5aSBrian Somers MD5Final(b, &Context); 1988fb5ef5aSBrian Somers } 1998fb5ef5aSBrian Somers 2008fb5ef5aSBrian Somers C += 16; 2018fb5ef5aSBrian Somers } 2028fb5ef5aSBrian Somers 2038fb5ef5aSBrian Somers /* 2048fb5ef5aSBrian Somers * The resulting plain text consists of a one-byte length, the text and 2058fb5ef5aSBrian Somers * maybe some padding. 2068fb5ef5aSBrian Somers */ 2078fb5ef5aSBrian Somers *len = *P; 2088fb5ef5aSBrian Somers if (*len > mlen - 1) { 2098fb5ef5aSBrian Somers log_Printf(LogWARN, "Mangled data seems to be garbage\n"); 2108fb5ef5aSBrian Somers *buf = NULL; 2118fb5ef5aSBrian Somers *len = 0; 2128fb5ef5aSBrian Somers return; 2138fb5ef5aSBrian Somers } 2148fb5ef5aSBrian Somers 2155d604c11SBrian Somers if ((*buf = malloc(*len)) == NULL) { 2165d604c11SBrian Somers log_Printf(LogWARN, "demangle: Out of memory (%lu bytes)\n", (u_long)*len); 2175d604c11SBrian Somers *len = 0; 2185d604c11SBrian Somers } else 2198fb5ef5aSBrian Somers memcpy(*buf, P + 1, *len); 2208fb5ef5aSBrian Somers } 221ff8e577bSBrian Somers #endif 222972a1bcfSBrian Somers 223ec3e98b8SHajimu UMEMOTO /* XXX: This should go into librarius. */ 224ec3e98b8SHajimu UMEMOTO #ifndef NOINET6 225ec3e98b8SHajimu UMEMOTO static uint8_t * 226ec3e98b8SHajimu UMEMOTO rad_cvt_ipv6prefix(const void *data, size_t len) 227ec3e98b8SHajimu UMEMOTO { 228ec3e98b8SHajimu UMEMOTO const size_t ipv6len = sizeof(struct in6_addr) + 2; 229ec3e98b8SHajimu UMEMOTO uint8_t *s; 230ec3e98b8SHajimu UMEMOTO 231ec3e98b8SHajimu UMEMOTO if (len > ipv6len) 232ec3e98b8SHajimu UMEMOTO return NULL; 233ec3e98b8SHajimu UMEMOTO s = malloc(ipv6len); 234ec3e98b8SHajimu UMEMOTO if (s != NULL) { 235ec3e98b8SHajimu UMEMOTO memset(s, 0, ipv6len); 236ec3e98b8SHajimu UMEMOTO memcpy(s, data, len); 237ec3e98b8SHajimu UMEMOTO } 238ec3e98b8SHajimu UMEMOTO return s; 239ec3e98b8SHajimu UMEMOTO } 240ec3e98b8SHajimu UMEMOTO #endif 241ec3e98b8SHajimu UMEMOTO 242f0cdd9c0SBrian Somers /* 243f0cdd9c0SBrian Somers * rad_continue_send_request() has given us `got' (non-zero). Deal with it. 244f0cdd9c0SBrian Somers */ 245f0cdd9c0SBrian Somers static void 246f0cdd9c0SBrian Somers radius_Process(struct radius *r, int got) 247972a1bcfSBrian Somers { 248972a1bcfSBrian Somers char *argv[MAXARGS], *nuke; 249f0cdd9c0SBrian Somers struct bundle *bundle; 250ff8e577bSBrian Somers int argc, addrs, res, width; 25128e610e3SBrian Somers size_t len; 25230949fd4SBrian Somers struct ncprange dest; 25330949fd4SBrian Somers struct ncpaddr gw; 254f0cdd9c0SBrian Somers const void *data; 255c42627ffSBrian Somers const char *stype; 256ff8e577bSBrian Somers u_int32_t ipaddr, vendor; 25730949fd4SBrian Somers struct in_addr ip; 2580fe74aa4SHajimu UMEMOTO #ifndef NOINET6 259ec3e98b8SHajimu UMEMOTO uint8_t ipv6addr[INET6_ADDRSTRLEN]; 2600fe74aa4SHajimu UMEMOTO struct in6_addr ip6; 2610fe74aa4SHajimu UMEMOTO #endif 262972a1bcfSBrian Somers 263f0cdd9c0SBrian Somers r->cx.fd = -1; /* Stop select()ing */ 264c42627ffSBrian Somers stype = r->cx.auth ? "auth" : "acct"; 265972a1bcfSBrian Somers 266972a1bcfSBrian Somers switch (got) { 267972a1bcfSBrian Somers case RAD_ACCESS_ACCEPT: 268e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 269e715b13bSBrian Somers "Radius(%s): ACCEPT received\n", stype); 270c42627ffSBrian Somers if (!r->cx.auth) { 271c42627ffSBrian Somers rad_close(r->cx.rad); 272c42627ffSBrian Somers return; 273c42627ffSBrian Somers } 274972a1bcfSBrian Somers break; 275972a1bcfSBrian Somers 276f0cdd9c0SBrian Somers case RAD_ACCESS_REJECT: 277e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 278e715b13bSBrian Somers "Radius(%s): REJECT received\n", stype); 279ff8e577bSBrian Somers if (!r->cx.auth) { 280f0cdd9c0SBrian Somers rad_close(r->cx.rad); 281f0cdd9c0SBrian Somers return; 282ff8e577bSBrian Somers } 283ff8e577bSBrian Somers break; 284f0cdd9c0SBrian Somers 285972a1bcfSBrian Somers case RAD_ACCESS_CHALLENGE: 286972a1bcfSBrian Somers /* we can't deal with this (for now) ! */ 287e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 288e715b13bSBrian Somers "Radius: CHALLENGE received (can't handle yet)\n"); 289c42627ffSBrian Somers if (r->cx.auth) 290f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 291f0cdd9c0SBrian Somers rad_close(r->cx.rad); 292f0cdd9c0SBrian Somers return; 293972a1bcfSBrian Somers 294794c9bbcSBrian Somers case RAD_ACCOUNTING_RESPONSE: 295e715b13bSBrian Somers /* 296e715b13bSBrian Somers * It's probably not ideal to log this at PHASE level as we'll see 297e715b13bSBrian Somers * too much stuff going to the log when ``set rad_alive'' is used. 298e715b13bSBrian Somers * So we differ from older behaviour (ppp version 3.1 and before) 299e715b13bSBrian Somers * and just log accounting responses to LogRADIUS. 300e715b13bSBrian Somers */ 301e715b13bSBrian Somers log_Printf(LogRADIUS, "Radius(%s): Accounting response received\n", 302e715b13bSBrian Somers stype); 303c42627ffSBrian Somers if (r->cx.auth) 304c42627ffSBrian Somers auth_Failure(r->cx.auth); /* unexpected !!! */ 305c42627ffSBrian Somers 306794c9bbcSBrian Somers /* No further processing for accounting requests, please */ 307794c9bbcSBrian Somers rad_close(r->cx.rad); 308794c9bbcSBrian Somers return; 309794c9bbcSBrian Somers 310972a1bcfSBrian Somers case -1: 311e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 312e715b13bSBrian Somers "radius(%s): %s\n", stype, rad_strerror(r->cx.rad)); 313c42627ffSBrian Somers if (r->cx.auth) 314f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 315f0cdd9c0SBrian Somers rad_close(r->cx.rad); 316f0cdd9c0SBrian Somers return; 317972a1bcfSBrian Somers 318972a1bcfSBrian Somers default: 319c42627ffSBrian Somers log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype, 320f0cdd9c0SBrian Somers got, rad_strerror(r->cx.rad)); 321c42627ffSBrian Somers if (r->cx.auth) 322f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 323f0cdd9c0SBrian Somers rad_close(r->cx.rad); 324f0cdd9c0SBrian Somers return; 325972a1bcfSBrian Somers } 326972a1bcfSBrian Somers 327ff8e577bSBrian Somers /* Let's see what we've got in our reply */ 328972a1bcfSBrian Somers r->ip.s_addr = r->mask.s_addr = INADDR_NONE; 329972a1bcfSBrian Somers r->mtu = 0; 330972a1bcfSBrian Somers r->vj = 0; 331ff8e577bSBrian Somers while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) { 332ff8e577bSBrian Somers switch (res) { 333972a1bcfSBrian Somers case RAD_FRAMED_IP_ADDRESS: 334972a1bcfSBrian Somers r->ip = rad_cvt_addr(data); 335e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 336e715b13bSBrian Somers " IP %s\n", inet_ntoa(r->ip)); 337972a1bcfSBrian Somers break; 338972a1bcfSBrian Somers 339bf1eaec5SBrian Somers case RAD_FILTER_ID: 340bf1eaec5SBrian Somers free(r->filterid); 341bf1eaec5SBrian Somers if ((r->filterid = rad_cvt_string(data, len)) == NULL) { 342bf1eaec5SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 343ff8e577bSBrian Somers auth_Failure(r->cx.auth); 344bf1eaec5SBrian Somers rad_close(r->cx.rad); 345bf1eaec5SBrian Somers return; 346bf1eaec5SBrian Somers } 347e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 348e715b13bSBrian Somers " Filter \"%s\"\n", r->filterid); 349bf1eaec5SBrian Somers break; 350bf1eaec5SBrian Somers 351bf1eaec5SBrian Somers case RAD_SESSION_TIMEOUT: 352bf1eaec5SBrian Somers r->sessiontime = rad_cvt_int(data); 353e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 354e715b13bSBrian Somers " Session-Timeout %lu\n", r->sessiontime); 355bf1eaec5SBrian Somers break; 356bf1eaec5SBrian Somers 357972a1bcfSBrian Somers case RAD_FRAMED_IP_NETMASK: 358972a1bcfSBrian Somers r->mask = rad_cvt_addr(data); 359e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 360e715b13bSBrian Somers " Netmask %s\n", inet_ntoa(r->mask)); 361972a1bcfSBrian Somers break; 362972a1bcfSBrian Somers 363972a1bcfSBrian Somers case RAD_FRAMED_MTU: 364972a1bcfSBrian Somers r->mtu = rad_cvt_int(data); 365e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 366e715b13bSBrian Somers " MTU %lu\n", r->mtu); 367972a1bcfSBrian Somers break; 368972a1bcfSBrian Somers 369972a1bcfSBrian Somers case RAD_FRAMED_ROUTING: 370972a1bcfSBrian Somers /* Disabled for now - should we automatically set up some filters ? */ 371972a1bcfSBrian Somers /* rad_cvt_int(data); */ 372972a1bcfSBrian Somers /* bit 1 = Send routing packets */ 373972a1bcfSBrian Somers /* bit 2 = Receive routing packets */ 374972a1bcfSBrian Somers break; 375972a1bcfSBrian Somers 376972a1bcfSBrian Somers case RAD_FRAMED_COMPRESSION: 377972a1bcfSBrian Somers r->vj = rad_cvt_int(data) == 1 ? 1 : 0; 378e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 379e715b13bSBrian Somers " VJ %sabled\n", r->vj ? "en" : "dis"); 380972a1bcfSBrian Somers break; 381972a1bcfSBrian Somers 382972a1bcfSBrian Somers case RAD_FRAMED_ROUTE: 383972a1bcfSBrian Somers /* 384972a1bcfSBrian Somers * We expect a string of the format ``dest[/bits] gw [metrics]'' 385972a1bcfSBrian Somers * Any specified metrics are ignored. MYADDR and HISADDR are 386972a1bcfSBrian Somers * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same 387972a1bcfSBrian Somers * as ``HISADDR''. 388972a1bcfSBrian Somers */ 389972a1bcfSBrian Somers 390972a1bcfSBrian Somers if ((nuke = rad_cvt_string(data, len)) == NULL) { 391f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 392ff8e577bSBrian Somers auth_Failure(r->cx.auth); 393f0cdd9c0SBrian Somers rad_close(r->cx.rad); 394f0cdd9c0SBrian Somers return; 395972a1bcfSBrian Somers } 396972a1bcfSBrian Somers 397e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 398e715b13bSBrian Somers " Route: %s\n", nuke); 399f0cdd9c0SBrian Somers bundle = r->cx.auth->physical->dl->bundle; 40030949fd4SBrian Somers ip.s_addr = INADDR_ANY; 4010fe74aa4SHajimu UMEMOTO ncpaddr_setip4(&gw, ip); 40230949fd4SBrian Somers ncprange_setip4host(&dest, ip); 403972a1bcfSBrian Somers argc = command_Interpret(nuke, strlen(nuke), argv); 404c39aa54eSBrian Somers if (argc < 0) 405c39aa54eSBrian Somers log_Printf(LogWARN, "radius: %s: Syntax error\n", 406c39aa54eSBrian Somers argc == 1 ? argv[0] : "\"\""); 407c39aa54eSBrian Somers else if (argc < 2) 408972a1bcfSBrian Somers log_Printf(LogWARN, "radius: %s: Invalid route\n", 409972a1bcfSBrian Somers argc == 1 ? argv[0] : "\"\""); 410972a1bcfSBrian Somers else if ((strcasecmp(argv[0], "default") != 0 && 41130949fd4SBrian Somers !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 41230949fd4SBrian Somers !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 413972a1bcfSBrian Somers log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 414972a1bcfSBrian Somers argv[0], argv[1]); 415972a1bcfSBrian Somers else { 41630949fd4SBrian Somers ncprange_getwidth(&dest, &width); 41730949fd4SBrian Somers if (width == 32 && strchr(argv[0], '/') == NULL) { 418972a1bcfSBrian Somers /* No mask specified - use the natural mask */ 41930949fd4SBrian Somers ncprange_getip4addr(&dest, &ip); 42030949fd4SBrian Somers ncprange_setip4mask(&dest, addr2mask(ip)); 42130949fd4SBrian Somers } 422972a1bcfSBrian Somers addrs = 0; 423972a1bcfSBrian Somers 424972a1bcfSBrian Somers if (!strncasecmp(argv[0], "HISADDR", 7)) 425972a1bcfSBrian Somers addrs = ROUTE_DSTHISADDR; 426972a1bcfSBrian Somers else if (!strncasecmp(argv[0], "MYADDR", 6)) 427972a1bcfSBrian Somers addrs = ROUTE_DSTMYADDR; 428972a1bcfSBrian Somers 42930949fd4SBrian Somers if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) { 430972a1bcfSBrian Somers addrs |= ROUTE_GWHISADDR; 43130949fd4SBrian Somers ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip); 432972a1bcfSBrian Somers } else if (strcasecmp(argv[1], "HISADDR") == 0) 433972a1bcfSBrian Somers addrs |= ROUTE_GWHISADDR; 434972a1bcfSBrian Somers 43530949fd4SBrian Somers route_Add(&r->routes, addrs, &dest, &gw); 436972a1bcfSBrian Somers } 437972a1bcfSBrian Somers free(nuke); 438972a1bcfSBrian Somers break; 439972a1bcfSBrian Somers 440ff8e577bSBrian Somers case RAD_REPLY_MESSAGE: 441ff8e577bSBrian Somers free(r->repstr); 442ff8e577bSBrian Somers if ((r->repstr = rad_cvt_string(data, len)) == NULL) { 443ff8e577bSBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 444ff8e577bSBrian Somers auth_Failure(r->cx.auth); 445ff8e577bSBrian Somers rad_close(r->cx.rad); 446ff8e577bSBrian Somers return; 447ff8e577bSBrian Somers } 448e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 449e715b13bSBrian Somers " Reply-Message \"%s\"\n", r->repstr); 450ff8e577bSBrian Somers break; 451ff8e577bSBrian Somers 4520fe74aa4SHajimu UMEMOTO #ifndef NOINET6 453ec3e98b8SHajimu UMEMOTO case RAD_FRAMED_IPV6_PREFIX: 454ec3e98b8SHajimu UMEMOTO free(r->ipv6prefix); 455ec3e98b8SHajimu UMEMOTO r->ipv6prefix = rad_cvt_ipv6prefix(data, len); 456ec3e98b8SHajimu UMEMOTO inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr)); 457e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 458e715b13bSBrian Somers " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]); 459ec3e98b8SHajimu UMEMOTO break; 460ec3e98b8SHajimu UMEMOTO 4610fe74aa4SHajimu UMEMOTO case RAD_FRAMED_IPV6_ROUTE: 4620fe74aa4SHajimu UMEMOTO /* 4630fe74aa4SHajimu UMEMOTO * We expect a string of the format ``dest[/bits] gw [metrics]'' 4640fe74aa4SHajimu UMEMOTO * Any specified metrics are ignored. MYADDR6 and HISADDR6 are 4650fe74aa4SHajimu UMEMOTO * understood for ``dest'' and ``gw'' and ``::'' is the same 4660fe74aa4SHajimu UMEMOTO * as ``HISADDR6''. 4670fe74aa4SHajimu UMEMOTO */ 4680fe74aa4SHajimu UMEMOTO 4690fe74aa4SHajimu UMEMOTO if ((nuke = rad_cvt_string(data, len)) == NULL) { 4700fe74aa4SHajimu UMEMOTO log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 4710fe74aa4SHajimu UMEMOTO auth_Failure(r->cx.auth); 4720fe74aa4SHajimu UMEMOTO rad_close(r->cx.rad); 4730fe74aa4SHajimu UMEMOTO return; 4740fe74aa4SHajimu UMEMOTO } 4750fe74aa4SHajimu UMEMOTO 476e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 477e715b13bSBrian Somers " IPv6 Route: %s\n", nuke); 4780fe74aa4SHajimu UMEMOTO bundle = r->cx.auth->physical->dl->bundle; 4790fe74aa4SHajimu UMEMOTO ncpaddr_setip6(&gw, &in6addr_any); 4800fe74aa4SHajimu UMEMOTO ncprange_set(&dest, &gw, 0); 4810fe74aa4SHajimu UMEMOTO argc = command_Interpret(nuke, strlen(nuke), argv); 4820fe74aa4SHajimu UMEMOTO if (argc < 0) 4830fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s: Syntax error\n", 4840fe74aa4SHajimu UMEMOTO argc == 1 ? argv[0] : "\"\""); 4850fe74aa4SHajimu UMEMOTO else if (argc < 2) 4860fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s: Invalid route\n", 4870fe74aa4SHajimu UMEMOTO argc == 1 ? argv[0] : "\"\""); 4880fe74aa4SHajimu UMEMOTO else if ((strcasecmp(argv[0], "default") != 0 && 4890fe74aa4SHajimu UMEMOTO !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 4900fe74aa4SHajimu UMEMOTO !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 4910fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 4920fe74aa4SHajimu UMEMOTO argv[0], argv[1]); 4930fe74aa4SHajimu UMEMOTO else { 4940fe74aa4SHajimu UMEMOTO addrs = 0; 4950fe74aa4SHajimu UMEMOTO 4960fe74aa4SHajimu UMEMOTO if (!strncasecmp(argv[0], "HISADDR6", 8)) 4970fe74aa4SHajimu UMEMOTO addrs = ROUTE_DSTHISADDR6; 4980fe74aa4SHajimu UMEMOTO else if (!strncasecmp(argv[0], "MYADDR6", 7)) 4990fe74aa4SHajimu UMEMOTO addrs = ROUTE_DSTMYADDR6; 5000fe74aa4SHajimu UMEMOTO 5010fe74aa4SHajimu UMEMOTO if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) { 5020fe74aa4SHajimu UMEMOTO addrs |= ROUTE_GWHISADDR6; 5030fe74aa4SHajimu UMEMOTO ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr); 5040fe74aa4SHajimu UMEMOTO } else if (strcasecmp(argv[1], "HISADDR6") == 0) 5050fe74aa4SHajimu UMEMOTO addrs |= ROUTE_GWHISADDR6; 5060fe74aa4SHajimu UMEMOTO 5070fe74aa4SHajimu UMEMOTO route_Add(&r->ipv6routes, addrs, &dest, &gw); 5080fe74aa4SHajimu UMEMOTO } 5090fe74aa4SHajimu UMEMOTO free(nuke); 5100fe74aa4SHajimu UMEMOTO break; 5110fe74aa4SHajimu UMEMOTO #endif 5120fe74aa4SHajimu UMEMOTO 513ff8e577bSBrian Somers case RAD_VENDOR_SPECIFIC: 514ff8e577bSBrian Somers if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) { 515ff8e577bSBrian Somers log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n", 516f0cdd9c0SBrian Somers rad_strerror(r->cx.rad)); 517f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 518f0cdd9c0SBrian Somers rad_close(r->cx.rad); 519ff8e577bSBrian Somers return; 520ff8e577bSBrian Somers } 521ff8e577bSBrian Somers 522ff8e577bSBrian Somers switch (vendor) { 523ff8e577bSBrian Somers case RAD_VENDOR_MICROSOFT: 524ff8e577bSBrian Somers switch (res) { 5258fb5ef5aSBrian Somers #ifndef NODES 526ff8e577bSBrian Somers case RAD_MICROSOFT_MS_CHAP_ERROR: 527ff8e577bSBrian Somers free(r->errstr); 528a95b23a6SBrian Somers if (len == 0) 529a95b23a6SBrian Somers r->errstr = NULL; 530a95b23a6SBrian Somers else { 53199cfc2e2SBrian Somers if (len < 3 || ((const char *)data)[1] != '=') { 53299cfc2e2SBrian Somers /* 53399cfc2e2SBrian Somers * Only point at the String field if we don't think the 53499cfc2e2SBrian Somers * peer has misformatted the response. 53599cfc2e2SBrian Somers */ 5361bb0b6deSAlexander Kabaev data = (const char *)data + 1; 53799cfc2e2SBrian Somers len--; 538579abfd8SBrian Somers } else 539579abfd8SBrian Somers log_Printf(LogWARN, "Warning: The MS-CHAP-Error " 540579abfd8SBrian Somers "attribute is mis-formatted. Compensating\n"); 54199cfc2e2SBrian Somers if ((r->errstr = rad_cvt_string((const char *)data, 54299cfc2e2SBrian Somers len)) == NULL) { 543ff8e577bSBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", 544ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 545ff8e577bSBrian Somers auth_Failure(r->cx.auth); 546ff8e577bSBrian Somers rad_close(r->cx.rad); 547ff8e577bSBrian Somers return; 548ff8e577bSBrian Somers } 549e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 550e715b13bSBrian Somers " MS-CHAP-Error \"%s\"\n", r->errstr); 551a95b23a6SBrian Somers } 552ff8e577bSBrian Somers break; 553ff8e577bSBrian Somers 554a16061b2SBrian Somers case RAD_MICROSOFT_MS_CHAP2_SUCCESS: 555a16061b2SBrian Somers free(r->msrepstr); 556a95b23a6SBrian Somers if (len == 0) 557a95b23a6SBrian Somers r->msrepstr = NULL; 558a95b23a6SBrian Somers else { 55999cfc2e2SBrian Somers if (len < 3 || ((const char *)data)[1] != '=') { 56099cfc2e2SBrian Somers /* 56199cfc2e2SBrian Somers * Only point at the String field if we don't think the 56299cfc2e2SBrian Somers * peer has misformatted the response. 56399cfc2e2SBrian Somers */ 5641bb0b6deSAlexander Kabaev data = (const char *)data + 1; 56599cfc2e2SBrian Somers len--; 566579abfd8SBrian Somers } else 567579abfd8SBrian Somers log_Printf(LogWARN, "Warning: The MS-CHAP2-Success " 568579abfd8SBrian Somers "attribute is mis-formatted. Compensating\n"); 56999cfc2e2SBrian Somers if ((r->msrepstr = rad_cvt_string((const char *)data, 57099cfc2e2SBrian Somers len)) == NULL) { 571a16061b2SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", 572a16061b2SBrian Somers rad_strerror(r->cx.rad)); 573a16061b2SBrian Somers auth_Failure(r->cx.auth); 574a16061b2SBrian Somers rad_close(r->cx.rad); 575a16061b2SBrian Somers return; 576a16061b2SBrian Somers } 577e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 578e715b13bSBrian Somers " MS-CHAP2-Success \"%s\"\n", r->msrepstr); 579a95b23a6SBrian Somers } 580a16061b2SBrian Somers break; 581a16061b2SBrian Somers 5828fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY: 5838fb5ef5aSBrian Somers r->mppe.policy = rad_cvt_int(data); 584e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 585e715b13bSBrian Somers " MS-MPPE-Encryption-Policy %s\n", 5868fb5ef5aSBrian Somers radius_policyname(r->mppe.policy)); 5878fb5ef5aSBrian Somers break; 5888fb5ef5aSBrian Somers 5898fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES: 5908fb5ef5aSBrian Somers r->mppe.types = rad_cvt_int(data); 591e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 592e715b13bSBrian Somers " MS-MPPE-Encryption-Types %s\n", 5938fb5ef5aSBrian Somers radius_typesname(r->mppe.types)); 5948fb5ef5aSBrian Somers break; 5958fb5ef5aSBrian Somers 5968fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_RECV_KEY: 5978fb5ef5aSBrian Somers free(r->mppe.recvkey); 5988fb5ef5aSBrian Somers demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen); 599e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 600e715b13bSBrian Somers " MS-MPPE-Recv-Key ********\n"); 6018fb5ef5aSBrian Somers break; 6028fb5ef5aSBrian Somers 6038fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_SEND_KEY: 6048fb5ef5aSBrian Somers demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen); 605e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 606e715b13bSBrian Somers " MS-MPPE-Send-Key ********\n"); 6078fb5ef5aSBrian Somers break; 6088fb5ef5aSBrian Somers #endif 6098fb5ef5aSBrian Somers 610ff8e577bSBrian Somers default: 611ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific " 612ff8e577bSBrian Somers "RADIUS attribute %d\n", res); 613ff8e577bSBrian Somers break; 614ff8e577bSBrian Somers } 615ff8e577bSBrian Somers break; 616ff8e577bSBrian Somers 617ff8e577bSBrian Somers default: 618ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n", 619ff8e577bSBrian Somers (unsigned long)vendor, res); 620ff8e577bSBrian Somers break; 621ff8e577bSBrian Somers } 622ff8e577bSBrian Somers break; 623ff8e577bSBrian Somers 624ff8e577bSBrian Somers default: 625ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res); 626ff8e577bSBrian Somers break; 627ff8e577bSBrian Somers } 628ff8e577bSBrian Somers } 629ff8e577bSBrian Somers 630ff8e577bSBrian Somers if (res == -1) { 631ff8e577bSBrian Somers log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n", 632ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 633ff8e577bSBrian Somers auth_Failure(r->cx.auth); 634ff8e577bSBrian Somers } else if (got == RAD_ACCESS_REJECT) 635ff8e577bSBrian Somers auth_Failure(r->cx.auth); 636ff8e577bSBrian Somers else { 637f0cdd9c0SBrian Somers r->valid = 1; 638f0cdd9c0SBrian Somers auth_Success(r->cx.auth); 639f0cdd9c0SBrian Somers } 640ff8e577bSBrian Somers rad_close(r->cx.rad); 641972a1bcfSBrian Somers } 642972a1bcfSBrian Somers 643f0cdd9c0SBrian Somers /* 6448e7bd08eSBrian Somers * We've either timed out or select()ed on the read descriptor 645f0cdd9c0SBrian Somers */ 646f0cdd9c0SBrian Somers static void 647f0cdd9c0SBrian Somers radius_Continue(struct radius *r, int sel) 648f0cdd9c0SBrian Somers { 649f0cdd9c0SBrian Somers struct timeval tv; 650f0cdd9c0SBrian Somers int got; 651972a1bcfSBrian Somers 652f0cdd9c0SBrian Somers timer_Stop(&r->cx.timer); 653f0cdd9c0SBrian Somers if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) { 654e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 655e715b13bSBrian Somers "Radius: Request re-sent\n"); 656f0cdd9c0SBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 657f0cdd9c0SBrian Somers timer_Start(&r->cx.timer); 658f0cdd9c0SBrian Somers return; 659f0cdd9c0SBrian Somers } 660f0cdd9c0SBrian Somers 661f0cdd9c0SBrian Somers radius_Process(r, got); 662f0cdd9c0SBrian Somers } 663f0cdd9c0SBrian Somers 664f0cdd9c0SBrian Somers /* 665f0cdd9c0SBrian Somers * Time to call rad_continue_send_request() - timed out. 666f0cdd9c0SBrian Somers */ 667f0cdd9c0SBrian Somers static void 668f0cdd9c0SBrian Somers radius_Timeout(void *v) 669f0cdd9c0SBrian Somers { 670f0cdd9c0SBrian Somers radius_Continue((struct radius *)v, 0); 671f0cdd9c0SBrian Somers } 672f0cdd9c0SBrian Somers 673f0cdd9c0SBrian Somers /* 674f0cdd9c0SBrian Somers * Time to call rad_continue_send_request() - something to read. 675f0cdd9c0SBrian Somers */ 676f0cdd9c0SBrian Somers static void 677057f1760SBrian Somers radius_Read(struct fdescriptor *d, struct bundle *bundle __unused, 678057f1760SBrian Somers const fd_set *fdset __unused) 679f0cdd9c0SBrian Somers { 680f0cdd9c0SBrian Somers radius_Continue(descriptor2radius(d), 1); 681f0cdd9c0SBrian Somers } 682f0cdd9c0SBrian Somers 683f0cdd9c0SBrian Somers /* 6848e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 685f0cdd9c0SBrian Somers */ 686f0cdd9c0SBrian Somers static int 687057f1760SBrian Somers radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w __unused, 688057f1760SBrian Somers fd_set *e __unused, int *n) 689f0cdd9c0SBrian Somers { 690f0cdd9c0SBrian Somers struct radius *rad = descriptor2radius(d); 691f0cdd9c0SBrian Somers 692f0cdd9c0SBrian Somers if (r && rad->cx.fd != -1) { 693f0cdd9c0SBrian Somers FD_SET(rad->cx.fd, r); 694f0cdd9c0SBrian Somers if (*n < rad->cx.fd + 1) 695f0cdd9c0SBrian Somers *n = rad->cx.fd + 1; 696f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd); 69782d6780cSBrian Somers return 1; 698972a1bcfSBrian Somers } 699972a1bcfSBrian Somers 700f0cdd9c0SBrian Somers return 0; 701f0cdd9c0SBrian Somers } 702f0cdd9c0SBrian Somers 703f0cdd9c0SBrian Somers /* 7048e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 705f0cdd9c0SBrian Somers */ 706f0cdd9c0SBrian Somers static int 707f013f33eSBrian Somers radius_IsSet(struct fdescriptor *d, const fd_set *fdset) 708f0cdd9c0SBrian Somers { 709f0cdd9c0SBrian Somers struct radius *r = descriptor2radius(d); 710f0cdd9c0SBrian Somers 711f0cdd9c0SBrian Somers return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset); 712f0cdd9c0SBrian Somers } 713f0cdd9c0SBrian Somers 714f0cdd9c0SBrian Somers /* 7158e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 716f0cdd9c0SBrian Somers */ 717f0cdd9c0SBrian Somers static int 718057f1760SBrian Somers radius_Write(struct fdescriptor *d __unused, struct bundle *bundle __unused, 719057f1760SBrian Somers const fd_set *fdset __unused) 720f0cdd9c0SBrian Somers { 721f0cdd9c0SBrian Somers /* We never want to write here ! */ 722f0cdd9c0SBrian Somers log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n"); 723f0cdd9c0SBrian Somers return 0; 724f0cdd9c0SBrian Somers } 725f0cdd9c0SBrian Somers 726f0cdd9c0SBrian Somers /* 727f0cdd9c0SBrian Somers * Initialise ourselves 728f0cdd9c0SBrian Somers */ 729f0cdd9c0SBrian Somers void 730f0cdd9c0SBrian Somers radius_Init(struct radius *r) 731f0cdd9c0SBrian Somers { 732f0cdd9c0SBrian Somers r->desc.type = RADIUS_DESCRIPTOR; 733f0cdd9c0SBrian Somers r->desc.UpdateSet = radius_UpdateSet; 734f0cdd9c0SBrian Somers r->desc.IsSet = radius_IsSet; 735f0cdd9c0SBrian Somers r->desc.Read = radius_Read; 736f0cdd9c0SBrian Somers r->desc.Write = radius_Write; 737ff8e577bSBrian Somers r->cx.fd = -1; 738ff8e577bSBrian Somers r->cx.rad = NULL; 739f0cdd9c0SBrian Somers memset(&r->cx.timer, '\0', sizeof r->cx.timer); 740ff8e577bSBrian Somers r->cx.auth = NULL; 741ff8e577bSBrian Somers r->valid = 0; 742ff8e577bSBrian Somers r->vj = 0; 743ff8e577bSBrian Somers r->ip.s_addr = INADDR_ANY; 744ff8e577bSBrian Somers r->mask.s_addr = INADDR_NONE; 745ff8e577bSBrian Somers r->routes = NULL; 746ff8e577bSBrian Somers r->mtu = DEF_MTU; 747a16061b2SBrian Somers r->msrepstr = NULL; 748ff8e577bSBrian Somers r->repstr = NULL; 7490fe74aa4SHajimu UMEMOTO #ifndef NOINET6 750ec3e98b8SHajimu UMEMOTO r->ipv6prefix = NULL; 7510fe74aa4SHajimu UMEMOTO r->ipv6routes = NULL; 7520fe74aa4SHajimu UMEMOTO #endif 753ff8e577bSBrian Somers r->errstr = NULL; 7548fb5ef5aSBrian Somers r->mppe.policy = 0; 7558fb5ef5aSBrian Somers r->mppe.types = 0; 7568fb5ef5aSBrian Somers r->mppe.recvkey = NULL; 7578fb5ef5aSBrian Somers r->mppe.recvkeylen = 0; 7588fb5ef5aSBrian Somers r->mppe.sendkey = NULL; 7598fb5ef5aSBrian Somers r->mppe.sendkeylen = 0; 760ff8e577bSBrian Somers *r->cfg.file = '\0';; 761794c9bbcSBrian Somers log_Printf(LogDEBUG, "Radius: radius_Init\n"); 762f0cdd9c0SBrian Somers } 763f0cdd9c0SBrian Somers 764f0cdd9c0SBrian Somers /* 765f0cdd9c0SBrian Somers * Forget everything and go back to initialised state. 766f0cdd9c0SBrian Somers */ 767f0cdd9c0SBrian Somers void 768f0cdd9c0SBrian Somers radius_Destroy(struct radius *r) 769f0cdd9c0SBrian Somers { 770f0cdd9c0SBrian Somers r->valid = 0; 771794c9bbcSBrian Somers log_Printf(LogDEBUG, "Radius: radius_Destroy\n"); 772f0cdd9c0SBrian Somers timer_Stop(&r->cx.timer); 773f0cdd9c0SBrian Somers route_DeleteAll(&r->routes); 7740fe74aa4SHajimu UMEMOTO #ifndef NOINET6 7750fe74aa4SHajimu UMEMOTO route_DeleteAll(&r->ipv6routes); 7760fe74aa4SHajimu UMEMOTO #endif 777bf1eaec5SBrian Somers free(r->filterid); 778bf1eaec5SBrian Somers r->filterid = NULL; 779a16061b2SBrian Somers free(r->msrepstr); 780a16061b2SBrian Somers r->msrepstr = NULL; 781ff8e577bSBrian Somers free(r->repstr); 782ff8e577bSBrian Somers r->repstr = NULL; 783ec3e98b8SHajimu UMEMOTO #ifndef NOINET6 784ec3e98b8SHajimu UMEMOTO free(r->ipv6prefix); 785ec3e98b8SHajimu UMEMOTO r->ipv6prefix = NULL; 786ec3e98b8SHajimu UMEMOTO #endif 787ff8e577bSBrian Somers free(r->errstr); 788ff8e577bSBrian Somers r->errstr = NULL; 7898fb5ef5aSBrian Somers free(r->mppe.recvkey); 7908fb5ef5aSBrian Somers r->mppe.recvkey = NULL; 7918fb5ef5aSBrian Somers r->mppe.recvkeylen = 0; 7928fb5ef5aSBrian Somers free(r->mppe.sendkey); 7938fb5ef5aSBrian Somers r->mppe.sendkey = NULL; 7948fb5ef5aSBrian Somers r->mppe.sendkeylen = 0; 795f0cdd9c0SBrian Somers if (r->cx.fd != -1) { 796f0cdd9c0SBrian Somers r->cx.fd = -1; 797f0cdd9c0SBrian Somers rad_close(r->cx.rad); 798f0cdd9c0SBrian Somers } 799f0cdd9c0SBrian Somers } 800f0cdd9c0SBrian Somers 801de59e178SBrian Somers static int 802de59e178SBrian Somers radius_put_physical_details(struct rad_handle *rad, struct physical *p) 803de59e178SBrian Somers { 804de59e178SBrian Somers int slot, type; 805de59e178SBrian Somers 806de59e178SBrian Somers type = RAD_VIRTUAL; 807de59e178SBrian Somers if (p->handler) 808de59e178SBrian Somers switch (p->handler->type) { 809de59e178SBrian Somers case I4B_DEVICE: 810de59e178SBrian Somers type = RAD_ISDN_SYNC; 811de59e178SBrian Somers break; 812de59e178SBrian Somers 813de59e178SBrian Somers case TTY_DEVICE: 814de59e178SBrian Somers type = RAD_ASYNC; 815de59e178SBrian Somers break; 816de59e178SBrian Somers 817de59e178SBrian Somers case ETHER_DEVICE: 818de59e178SBrian Somers type = RAD_ETHERNET; 819de59e178SBrian Somers break; 820de59e178SBrian Somers 821de59e178SBrian Somers case TCP_DEVICE: 822de59e178SBrian Somers case UDP_DEVICE: 823de59e178SBrian Somers case EXEC_DEVICE: 824de59e178SBrian Somers case ATM_DEVICE: 825de59e178SBrian Somers case NG_DEVICE: 826de59e178SBrian Somers type = RAD_VIRTUAL; 827de59e178SBrian Somers break; 828de59e178SBrian Somers } 829de59e178SBrian Somers 830de59e178SBrian Somers if (rad_put_int(rad, RAD_NAS_PORT_TYPE, type) != 0) { 831de59e178SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad)); 832de59e178SBrian Somers rad_close(rad); 833de59e178SBrian Somers return 0; 834de59e178SBrian Somers } 835de59e178SBrian Somers 836de59e178SBrian Somers if ((slot = physical_Slot(p)) >= 0) 837de59e178SBrian Somers if (rad_put_int(rad, RAD_NAS_PORT, slot) != 0) { 838de59e178SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad)); 839de59e178SBrian Somers rad_close(rad); 840de59e178SBrian Somers return 0; 841de59e178SBrian Somers } 842de59e178SBrian Somers 843de59e178SBrian Somers return 1; 844de59e178SBrian Somers } 845de59e178SBrian Somers 846f0cdd9c0SBrian Somers /* 847f0cdd9c0SBrian Somers * Start an authentication request to the RADIUS server. 848f0cdd9c0SBrian Somers */ 849a16061b2SBrian Somers int 850f0cdd9c0SBrian Somers radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, 851a16061b2SBrian Somers const char *key, int klen, const char *nchallenge, 852250be50bSBrian Somers int nclen) 853f0cdd9c0SBrian Somers { 85426e6a622SBrian Somers char hostname[MAXHOSTNAMELEN]; 855057f1760SBrian Somers struct timeval tv; 856057f1760SBrian Somers const char *what = "questionable"; /* silence warnings! */ 857057f1760SBrian Somers char *mac_addr; 858057f1760SBrian Somers int got; 859aadbb4eaSBrian Somers #if 0 860f10f5203SBrian Somers struct hostent *hp; 861f10f5203SBrian Somers struct in_addr hostaddr; 8628fb5ef5aSBrian Somers #endif 863ff8e577bSBrian Somers #ifndef NODES 864a16061b2SBrian Somers struct mschap_response msresp; 865a16061b2SBrian Somers struct mschap2_response msresp2; 866250be50bSBrian Somers const struct MSCHAPv2_resp *keyv2; 867ff8e577bSBrian Somers #endif 868f0cdd9c0SBrian Somers 869f0cdd9c0SBrian Somers if (!*r->cfg.file) 870a16061b2SBrian Somers return 0; 871f0cdd9c0SBrian Somers 872f0cdd9c0SBrian Somers if (r->cx.fd != -1) 873f0cdd9c0SBrian Somers /* 874f0cdd9c0SBrian Somers * We assume that our name/key/challenge is the same as last time, 875f0cdd9c0SBrian Somers * and just continue to wait for the RADIUS server(s). 876f0cdd9c0SBrian Somers */ 877a16061b2SBrian Somers return 1; 878f0cdd9c0SBrian Somers 879f0cdd9c0SBrian Somers radius_Destroy(r); 880f0cdd9c0SBrian Somers 881794c9bbcSBrian Somers if ((r->cx.rad = rad_auth_open()) == NULL) { 882794c9bbcSBrian Somers log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 883a16061b2SBrian Somers return 0; 884f0cdd9c0SBrian Somers } 885f0cdd9c0SBrian Somers 886f0cdd9c0SBrian Somers if (rad_config(r->cx.rad, r->cfg.file) != 0) { 887f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 888f0cdd9c0SBrian Somers rad_close(r->cx.rad); 889a16061b2SBrian Somers return 0; 890f0cdd9c0SBrian Somers } 891f0cdd9c0SBrian Somers 892f0cdd9c0SBrian Somers if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) { 893f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 894f0cdd9c0SBrian Somers rad_close(r->cx.rad); 895a16061b2SBrian Somers return 0; 896f0cdd9c0SBrian Somers } 897f0cdd9c0SBrian Somers 8984dc4e1eeSBrian Somers if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 || 899f0cdd9c0SBrian Somers rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 900f0cdd9c0SBrian Somers rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 901f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 902f0cdd9c0SBrian Somers rad_close(r->cx.rad); 903a16061b2SBrian Somers return 0; 904f0cdd9c0SBrian Somers } 905f0cdd9c0SBrian Somers 906ff8e577bSBrian Somers switch (authp->physical->link.lcp.want_auth) { 907ff8e577bSBrian Somers case PROTO_PAP: 908ff8e577bSBrian Somers /* We're talking PAP */ 909ff8e577bSBrian Somers if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) { 910ff8e577bSBrian Somers log_Printf(LogERROR, "PAP: rad_put_string: %s\n", 911ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 912ff8e577bSBrian Somers rad_close(r->cx.rad); 913a16061b2SBrian Somers return 0; 914ff8e577bSBrian Somers } 915e715b13bSBrian Somers what = "PAP"; 916ff8e577bSBrian Somers break; 917ff8e577bSBrian Somers 918ff8e577bSBrian Somers case PROTO_CHAP: 919ff8e577bSBrian Somers switch (authp->physical->link.lcp.want_authtype) { 920ff8e577bSBrian Somers case 0x5: 92150ca6ec3SBrian Somers if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 || 922a16061b2SBrian Somers rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) { 923f0cdd9c0SBrian Somers log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", 924f0cdd9c0SBrian Somers rad_strerror(r->cx.rad)); 925f0cdd9c0SBrian Somers rad_close(r->cx.rad); 926a16061b2SBrian Somers return 0; 927f0cdd9c0SBrian Somers } 928e715b13bSBrian Somers what = "CHAP"; 929ff8e577bSBrian Somers break; 930ff8e577bSBrian Somers 931ff8e577bSBrian Somers #ifndef NODES 932ff8e577bSBrian Somers case 0x80: 933ff8e577bSBrian Somers if (klen != 50) { 934a16061b2SBrian Somers log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen); 935f0cdd9c0SBrian Somers rad_close(r->cx.rad); 936a16061b2SBrian Somers return 0; 937f0cdd9c0SBrian Somers } 938a16061b2SBrian Somers 939ff8e577bSBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 940a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 941a16061b2SBrian Somers msresp.ident = *key; 942a16061b2SBrian Somers msresp.flags = 0x01; 943a16061b2SBrian Somers memcpy(msresp.lm_response, key + 1, 24); 944a16061b2SBrian Somers memcpy(msresp.nt_response, key + 25, 24); 945ff8e577bSBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 946a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp, 947a16061b2SBrian Somers sizeof msresp); 948e715b13bSBrian Somers what = "MSCHAP"; 949ff8e577bSBrian Somers break; 950ff8e577bSBrian Somers 951ff8e577bSBrian Somers case 0x81: 952250be50bSBrian Somers if (klen != sizeof(*keyv2) + 1) { 953a16061b2SBrian Somers log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen); 954a16061b2SBrian Somers rad_close(r->cx.rad); 955a16061b2SBrian Somers return 0; 956a16061b2SBrian Somers } 957a16061b2SBrian Somers 958250be50bSBrian Somers keyv2 = (const struct MSCHAPv2_resp *)(key + 1); 959a16061b2SBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 960a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 961a16061b2SBrian Somers msresp2.ident = *key; 962250be50bSBrian Somers msresp2.flags = keyv2->Flags; 963250be50bSBrian Somers memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response); 964a16061b2SBrian Somers memset(msresp2.reserved, '\0', sizeof msresp2.reserved); 965250be50bSBrian Somers memcpy(msresp2.pchallenge, keyv2->PeerChallenge, 966250be50bSBrian Somers sizeof msresp2.pchallenge); 967a16061b2SBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 968a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2, 969a16061b2SBrian Somers sizeof msresp2); 970e715b13bSBrian Somers what = "MSCHAPv2"; 971a16061b2SBrian Somers break; 972ff8e577bSBrian Somers #endif 973ff8e577bSBrian Somers default: 974ff8e577bSBrian Somers log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n", 975ff8e577bSBrian Somers authp->physical->link.lcp.want_authtype); 976ff8e577bSBrian Somers rad_close(r->cx.rad); 977a16061b2SBrian Somers return 0; 978ff8e577bSBrian Somers } 979ff8e577bSBrian Somers } 980f0cdd9c0SBrian Somers 981f10f5203SBrian Somers if (gethostname(hostname, sizeof hostname) != 0) 982f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 983f10f5203SBrian Somers else { 984aadbb4eaSBrian Somers #if 0 985f10f5203SBrian Somers if ((hp = gethostbyname(hostname)) != NULL) { 986f10f5203SBrian Somers hostaddr.s_addr = *(u_long *)hp->h_addr; 987f10f5203SBrian Somers if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 988f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 989f10f5203SBrian Somers rad_strerror(r->cx.rad)); 990f10f5203SBrian Somers rad_close(r->cx.rad); 991a16061b2SBrian Somers return 0; 992f10f5203SBrian Somers } 993f10f5203SBrian Somers } 994aadbb4eaSBrian Somers #endif 995f10f5203SBrian Somers if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 996f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 997f10f5203SBrian Somers rad_strerror(r->cx.rad)); 998f10f5203SBrian Somers rad_close(r->cx.rad); 999a16061b2SBrian Somers return 0; 1000f10f5203SBrian Somers } 1001f10f5203SBrian Somers } 1002f10f5203SBrian Somers 10035de776b9SBrian Somers if ((mac_addr = getenv("HISMACADDR")) != NULL && 10045de776b9SBrian Somers rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) { 10055de776b9SBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 10065de776b9SBrian Somers rad_close(r->cx.rad); 1007057f1760SBrian Somers return 0; 10085de776b9SBrian Somers } 10095de776b9SBrian Somers 1010de59e178SBrian Somers radius_put_physical_details(r->cx.rad, authp->physical); 1011f10f5203SBrian Somers 1012e715b13bSBrian Somers log_Printf(LogRADIUS, "Radius(auth): %s data sent for %s\n", what, name); 1013e715b13bSBrian Somers 1014c42627ffSBrian Somers r->cx.auth = authp; 1015f0cdd9c0SBrian Somers if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 1016f0cdd9c0SBrian Somers radius_Process(r, got); 1017f0cdd9c0SBrian Somers else { 1018e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 1019e715b13bSBrian Somers "Radius: Request sent\n"); 1020f0cdd9c0SBrian Somers log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 1021f0cdd9c0SBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 1022f0cdd9c0SBrian Somers r->cx.timer.func = radius_Timeout; 1023c42627ffSBrian Somers r->cx.timer.name = "radius auth"; 1024f0cdd9c0SBrian Somers r->cx.timer.arg = r; 1025f0cdd9c0SBrian Somers timer_Start(&r->cx.timer); 1026f0cdd9c0SBrian Somers } 1027a16061b2SBrian Somers 1028a16061b2SBrian Somers return 1; 1029f0cdd9c0SBrian Somers } 1030f0cdd9c0SBrian Somers 1031cf7c10d0SHajimu UMEMOTO /* Fetch IP, netmask from IPCP */ 1032cf7c10d0SHajimu UMEMOTO void 1033cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ip(struct radacct *ac, struct in_addr *peer_ip, 1034cf7c10d0SHajimu UMEMOTO struct in_addr *netmask) 1035cf7c10d0SHajimu UMEMOTO { 1036cf7c10d0SHajimu UMEMOTO ac->proto = PROTO_IPCP; 10372cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ip.addr, peer_ip, sizeof(ac->peer.ip.addr)); 10382cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ip.mask, netmask, sizeof(ac->peer.ip.mask)); 1039cf7c10d0SHajimu UMEMOTO } 1040cf7c10d0SHajimu UMEMOTO 1041cf7c10d0SHajimu UMEMOTO #ifndef NOINET6 1042cf7c10d0SHajimu UMEMOTO /* Fetch interface-id from IPV6CP */ 1043cf7c10d0SHajimu UMEMOTO void 1044cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ipv6(struct radacct *ac, u_char *ifid) 1045cf7c10d0SHajimu UMEMOTO { 1046cf7c10d0SHajimu UMEMOTO ac->proto = PROTO_IPV6CP; 10472cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ipv6.ifid, ifid, sizeof(ac->peer.ipv6.ifid)); 1048cf7c10d0SHajimu UMEMOTO } 1049cf7c10d0SHajimu UMEMOTO #endif 1050cf7c10d0SHajimu UMEMOTO 1051f0cdd9c0SBrian Somers /* 1052794c9bbcSBrian Somers * Send an accounting request to the RADIUS server 1053794c9bbcSBrian Somers */ 1054794c9bbcSBrian Somers void 1055794c9bbcSBrian Somers radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl, 1056cf7c10d0SHajimu UMEMOTO int acct_type, struct pppThroughput *stats) 1057794c9bbcSBrian Somers { 1058794c9bbcSBrian Somers struct timeval tv; 1059de59e178SBrian Somers int got; 106026e6a622SBrian Somers char hostname[MAXHOSTNAMELEN]; 10615de776b9SBrian Somers char *mac_addr; 1062aadbb4eaSBrian Somers #if 0 1063794c9bbcSBrian Somers struct hostent *hp; 1064794c9bbcSBrian Somers struct in_addr hostaddr; 10658fb5ef5aSBrian Somers #endif 1066794c9bbcSBrian Somers 1067794c9bbcSBrian Somers if (!*r->cfg.file) 1068794c9bbcSBrian Somers return; 1069794c9bbcSBrian Somers 1070794c9bbcSBrian Somers if (r->cx.fd != -1) 1071794c9bbcSBrian Somers /* 1072794c9bbcSBrian Somers * We assume that our name/key/challenge is the same as last time, 1073794c9bbcSBrian Somers * and just continue to wait for the RADIUS server(s). 1074794c9bbcSBrian Somers */ 1075794c9bbcSBrian Somers return; 1076794c9bbcSBrian Somers 10778fb5ef5aSBrian Somers timer_Stop(&r->cx.timer); 1078794c9bbcSBrian Somers 1079ba093e81SBrian Somers if ((r->cx.rad = rad_acct_open()) == NULL) { 1080794c9bbcSBrian Somers log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 1081794c9bbcSBrian Somers return; 1082794c9bbcSBrian Somers } 1083794c9bbcSBrian Somers 1084794c9bbcSBrian Somers if (rad_config(r->cx.rad, r->cfg.file) != 0) { 1085794c9bbcSBrian Somers log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 1086794c9bbcSBrian Somers rad_close(r->cx.rad); 1087794c9bbcSBrian Somers return; 1088794c9bbcSBrian Somers } 1089794c9bbcSBrian Somers 1090794c9bbcSBrian Somers if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) { 1091794c9bbcSBrian Somers log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 1092794c9bbcSBrian Somers rad_close(r->cx.rad); 1093794c9bbcSBrian Somers return; 1094794c9bbcSBrian Somers } 1095794c9bbcSBrian Somers 1096794c9bbcSBrian Somers /* Grab some accounting data and initialize structure */ 1097794c9bbcSBrian Somers if (acct_type == RAD_START) { 1098794c9bbcSBrian Somers ac->rad_parent = r; 1099794c9bbcSBrian Somers /* Fetch username from datalink */ 11004dc4e1eeSBrian Somers strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name); 1101794c9bbcSBrian Somers ac->user_name[AUTHLEN-1] = '\0'; 1102794c9bbcSBrian Somers 1103794c9bbcSBrian Somers ac->authentic = 2; /* Assume RADIUS verified auth data */ 1104794c9bbcSBrian Somers 1105794c9bbcSBrian Somers /* Generate a session ID */ 110612b5aabaSBrian Somers snprintf(ac->session_id, sizeof ac->session_id, "%s%ld-%s%lu", 110712b5aabaSBrian Somers dl->bundle->cfg.auth.name, (long)getpid(), 11084dc4e1eeSBrian Somers dl->peer.authname, (unsigned long)stats->uptime); 1109794c9bbcSBrian Somers 1110794c9bbcSBrian Somers /* And grab our MP socket name */ 1111794c9bbcSBrian Somers snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s", 1112794c9bbcSBrian Somers dl->bundle->ncp.mp.active ? 1113794c9bbcSBrian Somers dl->bundle->ncp.mp.server.socket.sun_path : ""); 1114794c9bbcSBrian Somers }; 1115794c9bbcSBrian Somers 1116794c9bbcSBrian Somers if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 || 1117794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 1118cf7c10d0SHajimu UMEMOTO rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 1119794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1120794c9bbcSBrian Somers rad_close(r->cx.rad); 1121794c9bbcSBrian Somers return; 1122794c9bbcSBrian Somers } 1123cf7c10d0SHajimu UMEMOTO switch (ac->proto) { 1124cf7c10d0SHajimu UMEMOTO case PROTO_IPCP: 11252cc2a59dSHajimu UMEMOTO if (rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS, 11267cbe2606SBrian Somers ac->peer.ip.addr) != 0 || 11272cc2a59dSHajimu UMEMOTO rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK, 11282cc2a59dSHajimu UMEMOTO ac->peer.ip.mask) != 0) { 1129cf7c10d0SHajimu UMEMOTO log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1130cf7c10d0SHajimu UMEMOTO rad_close(r->cx.rad); 1131cf7c10d0SHajimu UMEMOTO return; 1132cf7c10d0SHajimu UMEMOTO } 1133cf7c10d0SHajimu UMEMOTO break; 1134cf7c10d0SHajimu UMEMOTO #ifndef NOINET6 1135cf7c10d0SHajimu UMEMOTO case PROTO_IPV6CP: 11362cc2a59dSHajimu UMEMOTO if (rad_put_attr(r->cx.rad, RAD_FRAMED_INTERFACE_ID, ac->peer.ipv6.ifid, 11372cc2a59dSHajimu UMEMOTO sizeof(ac->peer.ipv6.ifid)) != 0) { 1138cf7c10d0SHajimu UMEMOTO log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad)); 1139cf7c10d0SHajimu UMEMOTO rad_close(r->cx.rad); 1140cf7c10d0SHajimu UMEMOTO return; 1141cf7c10d0SHajimu UMEMOTO } 1142ec3e98b8SHajimu UMEMOTO if (r->ipv6prefix) { 1143ec3e98b8SHajimu UMEMOTO /* 1144ec3e98b8SHajimu UMEMOTO * Since PPP doesn't delegate an IPv6 prefix to a peer, 1145ec3e98b8SHajimu UMEMOTO * Framed-IPv6-Prefix may be not used, actually. 1146ec3e98b8SHajimu UMEMOTO */ 1147ec3e98b8SHajimu UMEMOTO if (rad_put_attr(r->cx.rad, RAD_FRAMED_IPV6_PREFIX, r->ipv6prefix, 1148ec3e98b8SHajimu UMEMOTO sizeof(struct in6_addr) + 2) != 0) { 1149ec3e98b8SHajimu UMEMOTO log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad)); 1150ec3e98b8SHajimu UMEMOTO rad_close(r->cx.rad); 1151ec3e98b8SHajimu UMEMOTO return; 1152ec3e98b8SHajimu UMEMOTO } 1153ec3e98b8SHajimu UMEMOTO } 1154cf7c10d0SHajimu UMEMOTO break; 1155cf7c10d0SHajimu UMEMOTO #endif 1156cf7c10d0SHajimu UMEMOTO default: 1157cf7c10d0SHajimu UMEMOTO /* We don't log any protocol specific information */ 1158cf7c10d0SHajimu UMEMOTO break; 1159cf7c10d0SHajimu UMEMOTO } 1160794c9bbcSBrian Somers 11615de776b9SBrian Somers if ((mac_addr = getenv("HISMACADDR")) != NULL && 11625de776b9SBrian Somers rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) { 11635de776b9SBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 11645de776b9SBrian Somers rad_close(r->cx.rad); 11655de776b9SBrian Somers return; 11665de776b9SBrian Somers } 11675de776b9SBrian Somers 1168794c9bbcSBrian Somers if (gethostname(hostname, sizeof hostname) != 0) 1169794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 1170794c9bbcSBrian Somers else { 1171aadbb4eaSBrian Somers #if 0 1172794c9bbcSBrian Somers if ((hp = gethostbyname(hostname)) != NULL) { 1173794c9bbcSBrian Somers hostaddr.s_addr = *(u_long *)hp->h_addr; 1174794c9bbcSBrian Somers if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 1175794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1176794c9bbcSBrian Somers rad_strerror(r->cx.rad)); 1177794c9bbcSBrian Somers rad_close(r->cx.rad); 1178794c9bbcSBrian Somers return; 1179794c9bbcSBrian Somers } 1180794c9bbcSBrian Somers } 1181aadbb4eaSBrian Somers #endif 1182794c9bbcSBrian Somers if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 1183794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1184794c9bbcSBrian Somers rad_strerror(r->cx.rad)); 1185794c9bbcSBrian Somers rad_close(r->cx.rad); 1186794c9bbcSBrian Somers return; 1187794c9bbcSBrian Somers } 1188794c9bbcSBrian Somers } 1189794c9bbcSBrian Somers 1190de59e178SBrian Somers radius_put_physical_details(r->cx.rad, dl->physical); 1191794c9bbcSBrian Somers 1192794c9bbcSBrian Somers if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 || 1193794c9bbcSBrian Somers rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 || 1194794c9bbcSBrian Somers rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID, 1195794c9bbcSBrian Somers ac->multi_session_id) != 0 || 1196794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) { 1197794c9bbcSBrian Somers /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */ 1198794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1199794c9bbcSBrian Somers rad_close(r->cx.rad); 1200794c9bbcSBrian Somers return; 1201794c9bbcSBrian Somers } 1202794c9bbcSBrian Somers 1203e715b13bSBrian Somers if (acct_type == RAD_STOP || acct_type == RAD_ALIVE) 1204794c9bbcSBrian Somers /* Show some statistics */ 1205dfb3194aSDiomidis Spinellis if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn % UINT32_MAX) != 0 || 1206dfb3194aSDiomidis Spinellis rad_put_int(r->cx.rad, RAD_ACCT_INPUT_GIGAWORDS, stats->OctetsIn / UINT32_MAX) != 0 || 1207794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 || 1208dfb3194aSDiomidis Spinellis rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut % UINT32_MAX) != 0 || 1209dfb3194aSDiomidis Spinellis rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_GIGAWORDS, stats->OctetsOut / UINT32_MAX) != 0 || 1210794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut) 1211794c9bbcSBrian Somers != 0 || 1212794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats)) 1213794c9bbcSBrian Somers != 0) { 1214794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1215794c9bbcSBrian Somers rad_close(r->cx.rad); 1216794c9bbcSBrian Somers return; 1217794c9bbcSBrian Somers } 1218794c9bbcSBrian Somers 1219e715b13bSBrian Somers if (log_IsKept(LogPHASE) || log_IsKept(LogRADIUS)) { 1220057f1760SBrian Somers const char *what; 1221e715b13bSBrian Somers int level; 1222e715b13bSBrian Somers 1223e715b13bSBrian Somers switch (acct_type) { 1224e715b13bSBrian Somers case RAD_START: 1225e715b13bSBrian Somers what = "START"; 1226e715b13bSBrian Somers level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1227e715b13bSBrian Somers break; 1228e715b13bSBrian Somers case RAD_STOP: 1229e715b13bSBrian Somers what = "STOP"; 1230e715b13bSBrian Somers level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1231e715b13bSBrian Somers break; 1232e715b13bSBrian Somers case RAD_ALIVE: 1233e715b13bSBrian Somers what = "ALIVE"; 1234e715b13bSBrian Somers level = LogRADIUS; 1235e715b13bSBrian Somers break; 1236e715b13bSBrian Somers default: 1237e715b13bSBrian Somers what = "<unknown>"; 1238e715b13bSBrian Somers level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1239e715b13bSBrian Somers break; 1240e715b13bSBrian Somers } 1241e715b13bSBrian Somers log_Printf(level, "Radius(acct): %s data sent\n", what); 1242e715b13bSBrian Somers } 1243e715b13bSBrian Somers 1244c42627ffSBrian Somers r->cx.auth = NULL; /* Not valid for accounting requests */ 1245794c9bbcSBrian Somers if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 1246794c9bbcSBrian Somers radius_Process(r, got); 1247794c9bbcSBrian Somers else { 1248794c9bbcSBrian Somers log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 1249794c9bbcSBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 1250794c9bbcSBrian Somers r->cx.timer.func = radius_Timeout; 1251c42627ffSBrian Somers r->cx.timer.name = "radius acct"; 1252794c9bbcSBrian Somers r->cx.timer.arg = r; 1253794c9bbcSBrian Somers timer_Start(&r->cx.timer); 1254794c9bbcSBrian Somers } 1255794c9bbcSBrian Somers } 1256794c9bbcSBrian Somers 1257794c9bbcSBrian Somers /* 1258f0cdd9c0SBrian Somers * How do things look at the moment ? 1259f0cdd9c0SBrian Somers */ 1260972a1bcfSBrian Somers void 1261972a1bcfSBrian Somers radius_Show(struct radius *r, struct prompt *p) 1262972a1bcfSBrian Somers { 126374457d3dSBrian Somers prompt_Printf(p, " Radius config: %s", 126474457d3dSBrian Somers *r->cfg.file ? r->cfg.file : "none"); 1265972a1bcfSBrian Somers if (r->valid) { 1266972a1bcfSBrian Somers prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip)); 1267972a1bcfSBrian Somers prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask)); 1268972a1bcfSBrian Somers prompt_Printf(p, " MTU: %lu\n", r->mtu); 1269972a1bcfSBrian Somers prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis"); 1270ff8e577bSBrian Somers prompt_Printf(p, " Message: %s\n", r->repstr ? r->repstr : ""); 12718fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Enc Policy: %s\n", 12728fb5ef5aSBrian Somers radius_policyname(r->mppe.policy)); 12738fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Enc Types: %s\n", 12748fb5ef5aSBrian Somers radius_typesname(r->mppe.types)); 12758fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Recv Key: %seceived\n", 12768fb5ef5aSBrian Somers r->mppe.recvkey ? "R" : "Not r"); 12778fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Send Key: %seceived\n", 12788fb5ef5aSBrian Somers r->mppe.sendkey ? "R" : "Not r"); 1279a16061b2SBrian Somers prompt_Printf(p, " MS-CHAP2-Response: %s\n", 1280a16061b2SBrian Somers r->msrepstr ? r->msrepstr : ""); 1281ff8e577bSBrian Somers prompt_Printf(p, " Error Message: %s\n", r->errstr ? r->errstr : ""); 1282972a1bcfSBrian Somers if (r->routes) 1283972a1bcfSBrian Somers route_ShowSticky(p, r->routes, " Routes", 16); 12840fe74aa4SHajimu UMEMOTO #ifndef NOINET6 12850fe74aa4SHajimu UMEMOTO if (r->ipv6routes) 12860fe74aa4SHajimu UMEMOTO route_ShowSticky(p, r->ipv6routes, " IPv6 Routes", 16); 12870fe74aa4SHajimu UMEMOTO #endif 1288972a1bcfSBrian Somers } else 1289972a1bcfSBrian Somers prompt_Printf(p, " (not authenticated)\n"); 1290972a1bcfSBrian Somers } 1291e715b13bSBrian Somers 1292e715b13bSBrian Somers static void 1293e715b13bSBrian Somers radius_alive(void *v) 1294e715b13bSBrian Somers { 1295e715b13bSBrian Somers struct bundle *bundle = (struct bundle *)v; 1296e715b13bSBrian Somers 1297e715b13bSBrian Somers timer_Stop(&bundle->radius.alive.timer); 1298e715b13bSBrian Somers bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS; 1299e715b13bSBrian Somers if (bundle->radius.alive.timer.load) { 1300e715b13bSBrian Somers radius_Account(&bundle->radius, &bundle->radacct, 1301e715b13bSBrian Somers bundle->links, RAD_ALIVE, &bundle->ncp.ipcp.throughput); 1302e715b13bSBrian Somers timer_Start(&bundle->radius.alive.timer); 1303e715b13bSBrian Somers } 1304e715b13bSBrian Somers } 1305e715b13bSBrian Somers 1306e715b13bSBrian Somers void 1307e715b13bSBrian Somers radius_StartTimer(struct bundle *bundle) 1308e715b13bSBrian Somers { 1309e715b13bSBrian Somers if (bundle->radius.cfg.file && bundle->radius.alive.interval) { 1310e715b13bSBrian Somers bundle->radius.alive.timer.func = radius_alive; 1311e715b13bSBrian Somers bundle->radius.alive.timer.name = "radius alive"; 1312e715b13bSBrian Somers bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS; 1313e715b13bSBrian Somers bundle->radius.alive.timer.arg = bundle; 1314e715b13bSBrian Somers radius_alive(bundle); 1315e715b13bSBrian Somers } 1316e715b13bSBrian Somers } 1317e715b13bSBrian Somers 1318e715b13bSBrian Somers void 1319e715b13bSBrian Somers radius_StopTimer(struct radius *r) 1320e715b13bSBrian Somers { 1321e715b13bSBrian Somers timer_Stop(&r->alive.timer); 1322e715b13bSBrian Somers } 1323