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 3388044778SBrian Somers #include <sys/select.h> 346b457978SBrian Somers #include <sys/socket.h> 35972a1bcfSBrian Somers #include <netinet/in_systm.h> 36972a1bcfSBrian Somers #include <netinet/in.h> 37972a1bcfSBrian Somers #include <netinet/ip.h> 38972a1bcfSBrian Somers #include <arpa/inet.h> 39972a1bcfSBrian Somers #include <sys/un.h> 406b457978SBrian Somers #include <net/route.h> 41972a1bcfSBrian Somers 4210e629b9SBrian Somers #ifdef LOCALRAD 4310e629b9SBrian Somers #include "radlib.h" 44ff8e577bSBrian Somers #include "radlib_vs.h" 4510e629b9SBrian Somers #else 46972a1bcfSBrian Somers #include <radlib.h> 47ff8e577bSBrian Somers #include <radlib_vs.h> 4810e629b9SBrian Somers #endif 4910e629b9SBrian Somers 5010e629b9SBrian Somers #include <errno.h> 518fb5ef5aSBrian Somers #ifndef NODES 528fb5ef5aSBrian Somers #include <md5.h> 538fb5ef5aSBrian Somers #endif 546eafd353SBrian Somers #include <stdarg.h> 55972a1bcfSBrian Somers #include <stdio.h> 56972a1bcfSBrian Somers #include <stdlib.h> 57972a1bcfSBrian Somers #include <string.h> 58f0cdd9c0SBrian Somers #include <sys/time.h> 59972a1bcfSBrian Somers #include <termios.h> 60f10f5203SBrian Somers #include <unistd.h> 61f10f5203SBrian Somers #include <netdb.h> 62972a1bcfSBrian Somers 635d9e6103SBrian Somers #include "layer.h" 64972a1bcfSBrian Somers #include "defs.h" 65972a1bcfSBrian Somers #include "log.h" 66972a1bcfSBrian Somers #include "descriptor.h" 67972a1bcfSBrian Somers #include "prompt.h" 68972a1bcfSBrian Somers #include "timer.h" 69972a1bcfSBrian Somers #include "fsm.h" 70972a1bcfSBrian Somers #include "iplist.h" 71972a1bcfSBrian Somers #include "slcompress.h" 72972a1bcfSBrian Somers #include "throughput.h" 73972a1bcfSBrian Somers #include "lqr.h" 74972a1bcfSBrian Somers #include "hdlc.h" 75972a1bcfSBrian Somers #include "mbuf.h" 7630949fd4SBrian Somers #include "ncpaddr.h" 7730949fd4SBrian Somers #include "ip.h" 78972a1bcfSBrian Somers #include "ipcp.h" 7930949fd4SBrian Somers #include "ipv6cp.h" 80972a1bcfSBrian Somers #include "route.h" 81972a1bcfSBrian Somers #include "command.h" 82972a1bcfSBrian Somers #include "filter.h" 83972a1bcfSBrian Somers #include "lcp.h" 84972a1bcfSBrian Somers #include "ccp.h" 85972a1bcfSBrian Somers #include "link.h" 86972a1bcfSBrian Somers #include "mp.h" 87972a1bcfSBrian Somers #include "radius.h" 88f0cdd9c0SBrian Somers #include "auth.h" 89f0cdd9c0SBrian Somers #include "async.h" 90f0cdd9c0SBrian Somers #include "physical.h" 91f0cdd9c0SBrian Somers #include "chat.h" 92f0cdd9c0SBrian Somers #include "cbcp.h" 93f0cdd9c0SBrian Somers #include "chap.h" 94f0cdd9c0SBrian Somers #include "datalink.h" 9530949fd4SBrian Somers #include "ncp.h" 96972a1bcfSBrian Somers #include "bundle.h" 97ff8e577bSBrian Somers #include "proto.h" 98ff8e577bSBrian Somers 99ff8e577bSBrian Somers #ifndef NODES 100a16061b2SBrian Somers struct mschap_response { 101ff8e577bSBrian Somers u_char ident; 102ff8e577bSBrian Somers u_char flags; 103ff8e577bSBrian Somers u_char lm_response[24]; 104ff8e577bSBrian Somers u_char nt_response[24]; 105ff8e577bSBrian Somers }; 106a16061b2SBrian Somers 107a16061b2SBrian Somers struct mschap2_response { 108a16061b2SBrian Somers u_char ident; 109a16061b2SBrian Somers u_char flags; 110a16061b2SBrian Somers u_char pchallenge[16]; 111a16061b2SBrian Somers u_char reserved[8]; 112a16061b2SBrian Somers u_char response[24]; 113a16061b2SBrian Somers }; 1148fb5ef5aSBrian Somers 1158fb5ef5aSBrian Somers #define AUTH_LEN 16 1168fb5ef5aSBrian Somers #define SALT_LEN 2 1178fb5ef5aSBrian Somers #endif 1188fb5ef5aSBrian Somers 1198fb5ef5aSBrian Somers static const char * 1208fb5ef5aSBrian Somers radius_policyname(int policy) 1218fb5ef5aSBrian Somers { 1228fb5ef5aSBrian Somers switch(policy) { 1238fb5ef5aSBrian Somers case MPPE_POLICY_ALLOWED: 1248fb5ef5aSBrian Somers return "Allowed"; 1258fb5ef5aSBrian Somers case MPPE_POLICY_REQUIRED: 1268fb5ef5aSBrian Somers return "Required"; 1278fb5ef5aSBrian Somers } 1288fb5ef5aSBrian Somers return NumStr(policy, NULL, 0); 1298fb5ef5aSBrian Somers } 1308fb5ef5aSBrian Somers 1318fb5ef5aSBrian Somers static const char * 1328fb5ef5aSBrian Somers radius_typesname(int types) 1338fb5ef5aSBrian Somers { 1348fb5ef5aSBrian Somers switch(types) { 1358fb5ef5aSBrian Somers case MPPE_TYPE_40BIT: 1368fb5ef5aSBrian Somers return "40 bit"; 1378fb5ef5aSBrian Somers case MPPE_TYPE_128BIT: 1388fb5ef5aSBrian Somers return "128 bit"; 1398fb5ef5aSBrian Somers case MPPE_TYPE_40BIT|MPPE_TYPE_128BIT: 1408fb5ef5aSBrian Somers return "40 or 128 bit"; 1418fb5ef5aSBrian Somers } 1428fb5ef5aSBrian Somers return NumStr(types, NULL, 0); 1438fb5ef5aSBrian Somers } 1448fb5ef5aSBrian Somers 1458fb5ef5aSBrian Somers #ifndef NODES 1468fb5ef5aSBrian Somers static void 1478fb5ef5aSBrian Somers demangle(struct radius *r, const void *mangled, size_t mlen, 1488fb5ef5aSBrian Somers char **buf, size_t *len) 1498fb5ef5aSBrian Somers { 1508fb5ef5aSBrian Somers char R[AUTH_LEN]; /* variable names as per rfc2548 */ 1518fb5ef5aSBrian Somers const char *S; 1528fb5ef5aSBrian Somers u_char b[16]; 1538fb5ef5aSBrian Somers const u_char *A, *C; 1548fb5ef5aSBrian Somers MD5_CTX Context; 1558fb5ef5aSBrian Somers int Slen, i, Clen, Ppos; 1568fb5ef5aSBrian Somers u_char *P; 1578fb5ef5aSBrian Somers 1588fb5ef5aSBrian Somers if (mlen % 16 != SALT_LEN) { 1598fb5ef5aSBrian Somers log_Printf(LogWARN, "Cannot interpret mangled data of length %ld\n", 1608fb5ef5aSBrian Somers (u_long)mlen); 1618fb5ef5aSBrian Somers *buf = NULL; 1628fb5ef5aSBrian Somers *len = 0; 1638fb5ef5aSBrian Somers return; 1648fb5ef5aSBrian Somers } 1658fb5ef5aSBrian Somers 1668fb5ef5aSBrian Somers /* We need the RADIUS Request-Authenticator */ 1678fb5ef5aSBrian Somers if (rad_request_authenticator(r->cx.rad, R, sizeof R) != AUTH_LEN) { 1688fb5ef5aSBrian Somers log_Printf(LogWARN, "Cannot obtain the RADIUS request authenticator\n"); 1698fb5ef5aSBrian Somers *buf = NULL; 1708fb5ef5aSBrian Somers *len = 0; 1718fb5ef5aSBrian Somers return; 1728fb5ef5aSBrian Somers } 1738fb5ef5aSBrian Somers 1748fb5ef5aSBrian Somers A = (const u_char *)mangled; /* Salt comes first */ 1758fb5ef5aSBrian Somers C = (const u_char *)mangled + SALT_LEN; /* Then the ciphertext */ 1768fb5ef5aSBrian Somers Clen = mlen - SALT_LEN; 1778fb5ef5aSBrian Somers S = rad_server_secret(r->cx.rad); /* We need the RADIUS secret */ 1788fb5ef5aSBrian Somers Slen = strlen(S); 1798fb5ef5aSBrian Somers P = alloca(Clen); /* We derive our plaintext */ 1808fb5ef5aSBrian Somers 1818fb5ef5aSBrian Somers MD5Init(&Context); 1828fb5ef5aSBrian Somers MD5Update(&Context, S, Slen); 1838fb5ef5aSBrian Somers MD5Update(&Context, R, AUTH_LEN); 1848fb5ef5aSBrian Somers MD5Update(&Context, A, SALT_LEN); 1858fb5ef5aSBrian Somers MD5Final(b, &Context); 1868fb5ef5aSBrian Somers Ppos = 0; 1878fb5ef5aSBrian Somers 1888fb5ef5aSBrian Somers while (Clen) { 1898fb5ef5aSBrian Somers Clen -= 16; 1908fb5ef5aSBrian Somers 1918fb5ef5aSBrian Somers for (i = 0; i < 16; i++) 1928fb5ef5aSBrian Somers P[Ppos++] = C[i] ^ b[i]; 1938fb5ef5aSBrian Somers 1948fb5ef5aSBrian Somers if (Clen) { 1958fb5ef5aSBrian Somers MD5Init(&Context); 1968fb5ef5aSBrian Somers MD5Update(&Context, S, Slen); 1978fb5ef5aSBrian Somers MD5Update(&Context, C, 16); 1988fb5ef5aSBrian Somers MD5Final(b, &Context); 1998fb5ef5aSBrian Somers } 2008fb5ef5aSBrian Somers 2018fb5ef5aSBrian Somers C += 16; 2028fb5ef5aSBrian Somers } 2038fb5ef5aSBrian Somers 2048fb5ef5aSBrian Somers /* 2058fb5ef5aSBrian Somers * The resulting plain text consists of a one-byte length, the text and 2068fb5ef5aSBrian Somers * maybe some padding. 2078fb5ef5aSBrian Somers */ 2088fb5ef5aSBrian Somers *len = *P; 2098fb5ef5aSBrian Somers if (*len > mlen - 1) { 2108fb5ef5aSBrian Somers log_Printf(LogWARN, "Mangled data seems to be garbage\n"); 2118fb5ef5aSBrian Somers *buf = NULL; 2128fb5ef5aSBrian Somers *len = 0; 2138fb5ef5aSBrian Somers return; 2148fb5ef5aSBrian Somers } 2158fb5ef5aSBrian Somers 2165d604c11SBrian Somers if ((*buf = malloc(*len)) == NULL) { 2175d604c11SBrian Somers log_Printf(LogWARN, "demangle: Out of memory (%lu bytes)\n", (u_long)*len); 2185d604c11SBrian Somers *len = 0; 2195d604c11SBrian Somers } else 2208fb5ef5aSBrian Somers memcpy(*buf, P + 1, *len); 2218fb5ef5aSBrian Somers } 222ff8e577bSBrian Somers #endif 223972a1bcfSBrian Somers 224ec3e98b8SHajimu UMEMOTO /* XXX: This should go into librarius. */ 225ec3e98b8SHajimu UMEMOTO #ifndef NOINET6 226ec3e98b8SHajimu UMEMOTO static uint8_t * 227ec3e98b8SHajimu UMEMOTO rad_cvt_ipv6prefix(const void *data, size_t len) 228ec3e98b8SHajimu UMEMOTO { 229ec3e98b8SHajimu UMEMOTO const size_t ipv6len = sizeof(struct in6_addr) + 2; 230ec3e98b8SHajimu UMEMOTO uint8_t *s; 231ec3e98b8SHajimu UMEMOTO 232ec3e98b8SHajimu UMEMOTO if (len > ipv6len) 233ec3e98b8SHajimu UMEMOTO return NULL; 234ec3e98b8SHajimu UMEMOTO s = malloc(ipv6len); 235ec3e98b8SHajimu UMEMOTO if (s != NULL) { 236ec3e98b8SHajimu UMEMOTO memset(s, 0, ipv6len); 237ec3e98b8SHajimu UMEMOTO memcpy(s, data, len); 238ec3e98b8SHajimu UMEMOTO } 239ec3e98b8SHajimu UMEMOTO return s; 240ec3e98b8SHajimu UMEMOTO } 241ec3e98b8SHajimu UMEMOTO #endif 242ec3e98b8SHajimu UMEMOTO 243f0cdd9c0SBrian Somers /* 244f0cdd9c0SBrian Somers * rad_continue_send_request() has given us `got' (non-zero). Deal with it. 245f0cdd9c0SBrian Somers */ 246f0cdd9c0SBrian Somers static void 247f0cdd9c0SBrian Somers radius_Process(struct radius *r, int got) 248972a1bcfSBrian Somers { 249972a1bcfSBrian Somers char *argv[MAXARGS], *nuke; 250f0cdd9c0SBrian Somers struct bundle *bundle; 251ff8e577bSBrian Somers int argc, addrs, res, width; 25228e610e3SBrian Somers size_t len; 25330949fd4SBrian Somers struct ncprange dest; 25430949fd4SBrian Somers struct ncpaddr gw; 255f0cdd9c0SBrian Somers const void *data; 256c42627ffSBrian Somers const char *stype; 257ff8e577bSBrian Somers u_int32_t ipaddr, vendor; 25830949fd4SBrian Somers struct in_addr ip; 2590fe74aa4SHajimu UMEMOTO #ifndef NOINET6 260ec3e98b8SHajimu UMEMOTO uint8_t ipv6addr[INET6_ADDRSTRLEN]; 2610fe74aa4SHajimu UMEMOTO struct in6_addr ip6; 2620fe74aa4SHajimu UMEMOTO #endif 263972a1bcfSBrian Somers 264f0cdd9c0SBrian Somers r->cx.fd = -1; /* Stop select()ing */ 265c42627ffSBrian Somers stype = r->cx.auth ? "auth" : "acct"; 266972a1bcfSBrian Somers 267972a1bcfSBrian Somers switch (got) { 268972a1bcfSBrian Somers case RAD_ACCESS_ACCEPT: 269e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 270e715b13bSBrian Somers "Radius(%s): ACCEPT received\n", stype); 271c42627ffSBrian Somers if (!r->cx.auth) { 272c42627ffSBrian Somers rad_close(r->cx.rad); 273c42627ffSBrian Somers return; 274c42627ffSBrian Somers } 275972a1bcfSBrian Somers break; 276972a1bcfSBrian Somers 277f0cdd9c0SBrian Somers case RAD_ACCESS_REJECT: 278e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 279e715b13bSBrian Somers "Radius(%s): REJECT received\n", stype); 280ff8e577bSBrian Somers if (!r->cx.auth) { 281f0cdd9c0SBrian Somers rad_close(r->cx.rad); 282f0cdd9c0SBrian Somers return; 283ff8e577bSBrian Somers } 284ff8e577bSBrian Somers break; 285f0cdd9c0SBrian Somers 286972a1bcfSBrian Somers case RAD_ACCESS_CHALLENGE: 287972a1bcfSBrian Somers /* we can't deal with this (for now) ! */ 288e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 289e715b13bSBrian Somers "Radius: CHALLENGE received (can't handle yet)\n"); 290c42627ffSBrian Somers if (r->cx.auth) 291f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 292f0cdd9c0SBrian Somers rad_close(r->cx.rad); 293f0cdd9c0SBrian Somers return; 294972a1bcfSBrian Somers 295794c9bbcSBrian Somers case RAD_ACCOUNTING_RESPONSE: 296e715b13bSBrian Somers /* 297e715b13bSBrian Somers * It's probably not ideal to log this at PHASE level as we'll see 298e715b13bSBrian Somers * too much stuff going to the log when ``set rad_alive'' is used. 299e715b13bSBrian Somers * So we differ from older behaviour (ppp version 3.1 and before) 300e715b13bSBrian Somers * and just log accounting responses to LogRADIUS. 301e715b13bSBrian Somers */ 302e715b13bSBrian Somers log_Printf(LogRADIUS, "Radius(%s): Accounting response received\n", 303e715b13bSBrian Somers stype); 304c42627ffSBrian Somers if (r->cx.auth) 305c42627ffSBrian Somers auth_Failure(r->cx.auth); /* unexpected !!! */ 306c42627ffSBrian Somers 307794c9bbcSBrian Somers /* No further processing for accounting requests, please */ 308794c9bbcSBrian Somers rad_close(r->cx.rad); 309794c9bbcSBrian Somers return; 310794c9bbcSBrian Somers 311972a1bcfSBrian Somers case -1: 312e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 313e715b13bSBrian Somers "radius(%s): %s\n", stype, rad_strerror(r->cx.rad)); 314c42627ffSBrian Somers if (r->cx.auth) 315f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 316f0cdd9c0SBrian Somers rad_close(r->cx.rad); 317f0cdd9c0SBrian Somers return; 318972a1bcfSBrian Somers 319972a1bcfSBrian Somers default: 320c42627ffSBrian Somers log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype, 321f0cdd9c0SBrian Somers got, rad_strerror(r->cx.rad)); 322c42627ffSBrian Somers if (r->cx.auth) 323f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 324f0cdd9c0SBrian Somers rad_close(r->cx.rad); 325f0cdd9c0SBrian Somers return; 326972a1bcfSBrian Somers } 327972a1bcfSBrian Somers 328ff8e577bSBrian Somers /* Let's see what we've got in our reply */ 329972a1bcfSBrian Somers r->ip.s_addr = r->mask.s_addr = INADDR_NONE; 330972a1bcfSBrian Somers r->mtu = 0; 331972a1bcfSBrian Somers r->vj = 0; 332ff8e577bSBrian Somers while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) { 333ff8e577bSBrian Somers switch (res) { 334972a1bcfSBrian Somers case RAD_FRAMED_IP_ADDRESS: 335972a1bcfSBrian Somers r->ip = rad_cvt_addr(data); 336e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 337e715b13bSBrian Somers " IP %s\n", inet_ntoa(r->ip)); 338972a1bcfSBrian Somers break; 339972a1bcfSBrian Somers 340bf1eaec5SBrian Somers case RAD_FILTER_ID: 341bf1eaec5SBrian Somers free(r->filterid); 342bf1eaec5SBrian Somers if ((r->filterid = rad_cvt_string(data, len)) == NULL) { 343bf1eaec5SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 344ff8e577bSBrian Somers auth_Failure(r->cx.auth); 345bf1eaec5SBrian Somers rad_close(r->cx.rad); 346bf1eaec5SBrian Somers return; 347bf1eaec5SBrian Somers } 348e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 349e715b13bSBrian Somers " Filter \"%s\"\n", r->filterid); 350bf1eaec5SBrian Somers break; 351bf1eaec5SBrian Somers 352bf1eaec5SBrian Somers case RAD_SESSION_TIMEOUT: 353bf1eaec5SBrian Somers r->sessiontime = rad_cvt_int(data); 354e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 355e715b13bSBrian Somers " Session-Timeout %lu\n", r->sessiontime); 356bf1eaec5SBrian Somers break; 357bf1eaec5SBrian Somers 358972a1bcfSBrian Somers case RAD_FRAMED_IP_NETMASK: 359972a1bcfSBrian Somers r->mask = rad_cvt_addr(data); 360e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 361e715b13bSBrian Somers " Netmask %s\n", inet_ntoa(r->mask)); 362972a1bcfSBrian Somers break; 363972a1bcfSBrian Somers 364972a1bcfSBrian Somers case RAD_FRAMED_MTU: 365972a1bcfSBrian Somers r->mtu = rad_cvt_int(data); 366e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 367e715b13bSBrian Somers " MTU %lu\n", r->mtu); 368972a1bcfSBrian Somers break; 369972a1bcfSBrian Somers 370972a1bcfSBrian Somers case RAD_FRAMED_ROUTING: 371972a1bcfSBrian Somers /* Disabled for now - should we automatically set up some filters ? */ 372972a1bcfSBrian Somers /* rad_cvt_int(data); */ 373972a1bcfSBrian Somers /* bit 1 = Send routing packets */ 374972a1bcfSBrian Somers /* bit 2 = Receive routing packets */ 375972a1bcfSBrian Somers break; 376972a1bcfSBrian Somers 377972a1bcfSBrian Somers case RAD_FRAMED_COMPRESSION: 378972a1bcfSBrian Somers r->vj = rad_cvt_int(data) == 1 ? 1 : 0; 379e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 380e715b13bSBrian Somers " VJ %sabled\n", r->vj ? "en" : "dis"); 381972a1bcfSBrian Somers break; 382972a1bcfSBrian Somers 383972a1bcfSBrian Somers case RAD_FRAMED_ROUTE: 384972a1bcfSBrian Somers /* 385972a1bcfSBrian Somers * We expect a string of the format ``dest[/bits] gw [metrics]'' 386972a1bcfSBrian Somers * Any specified metrics are ignored. MYADDR and HISADDR are 387972a1bcfSBrian Somers * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same 388972a1bcfSBrian Somers * as ``HISADDR''. 389972a1bcfSBrian Somers */ 390972a1bcfSBrian Somers 391972a1bcfSBrian Somers if ((nuke = rad_cvt_string(data, len)) == NULL) { 392f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 393ff8e577bSBrian Somers auth_Failure(r->cx.auth); 394f0cdd9c0SBrian Somers rad_close(r->cx.rad); 395f0cdd9c0SBrian Somers return; 396972a1bcfSBrian Somers } 397972a1bcfSBrian Somers 398e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 399e715b13bSBrian Somers " Route: %s\n", nuke); 400f0cdd9c0SBrian Somers bundle = r->cx.auth->physical->dl->bundle; 40130949fd4SBrian Somers ip.s_addr = INADDR_ANY; 4020fe74aa4SHajimu UMEMOTO ncpaddr_setip4(&gw, ip); 40330949fd4SBrian Somers ncprange_setip4host(&dest, ip); 404972a1bcfSBrian Somers argc = command_Interpret(nuke, strlen(nuke), argv); 405c39aa54eSBrian Somers if (argc < 0) 406c39aa54eSBrian Somers log_Printf(LogWARN, "radius: %s: Syntax error\n", 407c39aa54eSBrian Somers argc == 1 ? argv[0] : "\"\""); 408c39aa54eSBrian Somers else if (argc < 2) 409972a1bcfSBrian Somers log_Printf(LogWARN, "radius: %s: Invalid route\n", 410972a1bcfSBrian Somers argc == 1 ? argv[0] : "\"\""); 411972a1bcfSBrian Somers else if ((strcasecmp(argv[0], "default") != 0 && 41230949fd4SBrian Somers !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 41330949fd4SBrian Somers !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 414972a1bcfSBrian Somers log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 415972a1bcfSBrian Somers argv[0], argv[1]); 416972a1bcfSBrian Somers else { 41730949fd4SBrian Somers ncprange_getwidth(&dest, &width); 41830949fd4SBrian Somers if (width == 32 && strchr(argv[0], '/') == NULL) { 419972a1bcfSBrian Somers /* No mask specified - use the natural mask */ 42030949fd4SBrian Somers ncprange_getip4addr(&dest, &ip); 42130949fd4SBrian Somers ncprange_setip4mask(&dest, addr2mask(ip)); 42230949fd4SBrian Somers } 423972a1bcfSBrian Somers addrs = 0; 424972a1bcfSBrian Somers 425972a1bcfSBrian Somers if (!strncasecmp(argv[0], "HISADDR", 7)) 426972a1bcfSBrian Somers addrs = ROUTE_DSTHISADDR; 427972a1bcfSBrian Somers else if (!strncasecmp(argv[0], "MYADDR", 6)) 428972a1bcfSBrian Somers addrs = ROUTE_DSTMYADDR; 429972a1bcfSBrian Somers 43030949fd4SBrian Somers if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) { 431972a1bcfSBrian Somers addrs |= ROUTE_GWHISADDR; 43230949fd4SBrian Somers ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip); 433972a1bcfSBrian Somers } else if (strcasecmp(argv[1], "HISADDR") == 0) 434972a1bcfSBrian Somers addrs |= ROUTE_GWHISADDR; 435972a1bcfSBrian Somers 43630949fd4SBrian Somers route_Add(&r->routes, addrs, &dest, &gw); 437972a1bcfSBrian Somers } 438972a1bcfSBrian Somers free(nuke); 439972a1bcfSBrian Somers break; 440972a1bcfSBrian Somers 441ff8e577bSBrian Somers case RAD_REPLY_MESSAGE: 442ff8e577bSBrian Somers free(r->repstr); 443ff8e577bSBrian Somers if ((r->repstr = rad_cvt_string(data, len)) == NULL) { 444ff8e577bSBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 445ff8e577bSBrian Somers auth_Failure(r->cx.auth); 446ff8e577bSBrian Somers rad_close(r->cx.rad); 447ff8e577bSBrian Somers return; 448ff8e577bSBrian Somers } 449e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 450e715b13bSBrian Somers " Reply-Message \"%s\"\n", r->repstr); 451ff8e577bSBrian Somers break; 452ff8e577bSBrian Somers 4530fe74aa4SHajimu UMEMOTO #ifndef NOINET6 454ec3e98b8SHajimu UMEMOTO case RAD_FRAMED_IPV6_PREFIX: 455ec3e98b8SHajimu UMEMOTO free(r->ipv6prefix); 456a404ab16SHajimu UMEMOTO if ((r->ipv6prefix = rad_cvt_ipv6prefix(data, len)) == NULL) { 457a404ab16SHajimu UMEMOTO log_Printf(LogERROR, "rad_cvt_ipv6prefix: %s\n", 458a404ab16SHajimu UMEMOTO "Malformed attribute in response"); 459a404ab16SHajimu UMEMOTO auth_Failure(r->cx.auth); 460a404ab16SHajimu UMEMOTO rad_close(r->cx.rad); 461a404ab16SHajimu UMEMOTO return; 462a404ab16SHajimu UMEMOTO } 463ec3e98b8SHajimu UMEMOTO inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr)); 464e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 465e715b13bSBrian Somers " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]); 466ec3e98b8SHajimu UMEMOTO break; 467ec3e98b8SHajimu UMEMOTO 4680fe74aa4SHajimu UMEMOTO case RAD_FRAMED_IPV6_ROUTE: 4690fe74aa4SHajimu UMEMOTO /* 4700fe74aa4SHajimu UMEMOTO * We expect a string of the format ``dest[/bits] gw [metrics]'' 4710fe74aa4SHajimu UMEMOTO * Any specified metrics are ignored. MYADDR6 and HISADDR6 are 4720fe74aa4SHajimu UMEMOTO * understood for ``dest'' and ``gw'' and ``::'' is the same 4730fe74aa4SHajimu UMEMOTO * as ``HISADDR6''. 4740fe74aa4SHajimu UMEMOTO */ 4750fe74aa4SHajimu UMEMOTO 4760fe74aa4SHajimu UMEMOTO if ((nuke = rad_cvt_string(data, len)) == NULL) { 4770fe74aa4SHajimu UMEMOTO log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 4780fe74aa4SHajimu UMEMOTO auth_Failure(r->cx.auth); 4790fe74aa4SHajimu UMEMOTO rad_close(r->cx.rad); 4800fe74aa4SHajimu UMEMOTO return; 4810fe74aa4SHajimu UMEMOTO } 4820fe74aa4SHajimu UMEMOTO 483e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 484e715b13bSBrian Somers " IPv6 Route: %s\n", nuke); 4850fe74aa4SHajimu UMEMOTO bundle = r->cx.auth->physical->dl->bundle; 4860fe74aa4SHajimu UMEMOTO ncpaddr_setip6(&gw, &in6addr_any); 4870fe74aa4SHajimu UMEMOTO ncprange_set(&dest, &gw, 0); 4880fe74aa4SHajimu UMEMOTO argc = command_Interpret(nuke, strlen(nuke), argv); 4890fe74aa4SHajimu UMEMOTO if (argc < 0) 4900fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s: Syntax error\n", 4910fe74aa4SHajimu UMEMOTO argc == 1 ? argv[0] : "\"\""); 4920fe74aa4SHajimu UMEMOTO else if (argc < 2) 4930fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s: Invalid route\n", 4940fe74aa4SHajimu UMEMOTO argc == 1 ? argv[0] : "\"\""); 4950fe74aa4SHajimu UMEMOTO else if ((strcasecmp(argv[0], "default") != 0 && 4960fe74aa4SHajimu UMEMOTO !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 4970fe74aa4SHajimu UMEMOTO !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 4980fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 4990fe74aa4SHajimu UMEMOTO argv[0], argv[1]); 5000fe74aa4SHajimu UMEMOTO else { 5010fe74aa4SHajimu UMEMOTO addrs = 0; 5020fe74aa4SHajimu UMEMOTO 5030fe74aa4SHajimu UMEMOTO if (!strncasecmp(argv[0], "HISADDR6", 8)) 5040fe74aa4SHajimu UMEMOTO addrs = ROUTE_DSTHISADDR6; 5050fe74aa4SHajimu UMEMOTO else if (!strncasecmp(argv[0], "MYADDR6", 7)) 5060fe74aa4SHajimu UMEMOTO addrs = ROUTE_DSTMYADDR6; 5070fe74aa4SHajimu UMEMOTO 5080fe74aa4SHajimu UMEMOTO if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) { 5090fe74aa4SHajimu UMEMOTO addrs |= ROUTE_GWHISADDR6; 5100fe74aa4SHajimu UMEMOTO ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr); 5110fe74aa4SHajimu UMEMOTO } else if (strcasecmp(argv[1], "HISADDR6") == 0) 5120fe74aa4SHajimu UMEMOTO addrs |= ROUTE_GWHISADDR6; 5130fe74aa4SHajimu UMEMOTO 5140fe74aa4SHajimu UMEMOTO route_Add(&r->ipv6routes, addrs, &dest, &gw); 5150fe74aa4SHajimu UMEMOTO } 5160fe74aa4SHajimu UMEMOTO free(nuke); 5170fe74aa4SHajimu UMEMOTO break; 5180fe74aa4SHajimu UMEMOTO #endif 5190fe74aa4SHajimu UMEMOTO 520ff8e577bSBrian Somers case RAD_VENDOR_SPECIFIC: 521ff8e577bSBrian Somers if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) { 522ff8e577bSBrian Somers log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n", 523f0cdd9c0SBrian Somers rad_strerror(r->cx.rad)); 524f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 525f0cdd9c0SBrian Somers rad_close(r->cx.rad); 526ff8e577bSBrian Somers return; 527ff8e577bSBrian Somers } 528ff8e577bSBrian Somers 529ff8e577bSBrian Somers switch (vendor) { 530ff8e577bSBrian Somers case RAD_VENDOR_MICROSOFT: 531ff8e577bSBrian Somers switch (res) { 5328fb5ef5aSBrian Somers #ifndef NODES 533ff8e577bSBrian Somers case RAD_MICROSOFT_MS_CHAP_ERROR: 534ff8e577bSBrian Somers free(r->errstr); 535a95b23a6SBrian Somers if (len == 0) 536a95b23a6SBrian Somers r->errstr = NULL; 537a95b23a6SBrian Somers else { 53899cfc2e2SBrian Somers if (len < 3 || ((const char *)data)[1] != '=') { 53999cfc2e2SBrian Somers /* 54099cfc2e2SBrian Somers * Only point at the String field if we don't think the 54199cfc2e2SBrian Somers * peer has misformatted the response. 54299cfc2e2SBrian Somers */ 5431bb0b6deSAlexander Kabaev data = (const char *)data + 1; 54499cfc2e2SBrian Somers len--; 545579abfd8SBrian Somers } else 546579abfd8SBrian Somers log_Printf(LogWARN, "Warning: The MS-CHAP-Error " 547579abfd8SBrian Somers "attribute is mis-formatted. Compensating\n"); 54899cfc2e2SBrian Somers if ((r->errstr = rad_cvt_string((const char *)data, 54999cfc2e2SBrian Somers len)) == NULL) { 550ff8e577bSBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", 551ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 552ff8e577bSBrian Somers auth_Failure(r->cx.auth); 553ff8e577bSBrian Somers rad_close(r->cx.rad); 554ff8e577bSBrian Somers return; 555ff8e577bSBrian Somers } 556e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 557e715b13bSBrian Somers " MS-CHAP-Error \"%s\"\n", r->errstr); 558a95b23a6SBrian Somers } 559ff8e577bSBrian Somers break; 560ff8e577bSBrian Somers 561a16061b2SBrian Somers case RAD_MICROSOFT_MS_CHAP2_SUCCESS: 562a16061b2SBrian Somers free(r->msrepstr); 563a95b23a6SBrian Somers if (len == 0) 564a95b23a6SBrian Somers r->msrepstr = NULL; 565a95b23a6SBrian Somers else { 56699cfc2e2SBrian Somers if (len < 3 || ((const char *)data)[1] != '=') { 56799cfc2e2SBrian Somers /* 56899cfc2e2SBrian Somers * Only point at the String field if we don't think the 56999cfc2e2SBrian Somers * peer has misformatted the response. 57099cfc2e2SBrian Somers */ 5711bb0b6deSAlexander Kabaev data = (const char *)data + 1; 57299cfc2e2SBrian Somers len--; 573579abfd8SBrian Somers } else 574579abfd8SBrian Somers log_Printf(LogWARN, "Warning: The MS-CHAP2-Success " 575579abfd8SBrian Somers "attribute is mis-formatted. Compensating\n"); 57699cfc2e2SBrian Somers if ((r->msrepstr = rad_cvt_string((const char *)data, 57799cfc2e2SBrian Somers len)) == NULL) { 578a16061b2SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", 579a16061b2SBrian Somers rad_strerror(r->cx.rad)); 580a16061b2SBrian Somers auth_Failure(r->cx.auth); 581a16061b2SBrian Somers rad_close(r->cx.rad); 582a16061b2SBrian Somers return; 583a16061b2SBrian Somers } 584e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 585e715b13bSBrian Somers " MS-CHAP2-Success \"%s\"\n", r->msrepstr); 586a95b23a6SBrian Somers } 587a16061b2SBrian Somers break; 588a16061b2SBrian Somers 5898fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY: 5908fb5ef5aSBrian Somers r->mppe.policy = rad_cvt_int(data); 591e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 592e715b13bSBrian Somers " MS-MPPE-Encryption-Policy %s\n", 5938fb5ef5aSBrian Somers radius_policyname(r->mppe.policy)); 5948fb5ef5aSBrian Somers break; 5958fb5ef5aSBrian Somers 5968fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES: 5978fb5ef5aSBrian Somers r->mppe.types = rad_cvt_int(data); 598e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 599e715b13bSBrian Somers " MS-MPPE-Encryption-Types %s\n", 6008fb5ef5aSBrian Somers radius_typesname(r->mppe.types)); 6018fb5ef5aSBrian Somers break; 6028fb5ef5aSBrian Somers 6038fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_RECV_KEY: 6048fb5ef5aSBrian Somers free(r->mppe.recvkey); 6058fb5ef5aSBrian Somers demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen); 606e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 607e715b13bSBrian Somers " MS-MPPE-Recv-Key ********\n"); 6088fb5ef5aSBrian Somers break; 6098fb5ef5aSBrian Somers 6108fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_SEND_KEY: 6118fb5ef5aSBrian Somers demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen); 612e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 613e715b13bSBrian Somers " MS-MPPE-Send-Key ********\n"); 6148fb5ef5aSBrian Somers break; 6158fb5ef5aSBrian Somers #endif 6168fb5ef5aSBrian Somers 617ff8e577bSBrian Somers default: 618ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific " 619ff8e577bSBrian Somers "RADIUS attribute %d\n", res); 620ff8e577bSBrian Somers break; 621ff8e577bSBrian Somers } 622ff8e577bSBrian Somers break; 623ff8e577bSBrian Somers 624ff8e577bSBrian Somers default: 625ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n", 626ff8e577bSBrian Somers (unsigned long)vendor, res); 627ff8e577bSBrian Somers break; 628ff8e577bSBrian Somers } 629ff8e577bSBrian Somers break; 630ff8e577bSBrian Somers 631ff8e577bSBrian Somers default: 632ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res); 633ff8e577bSBrian Somers break; 634ff8e577bSBrian Somers } 635ff8e577bSBrian Somers } 636ff8e577bSBrian Somers 637ff8e577bSBrian Somers if (res == -1) { 638ff8e577bSBrian Somers log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n", 639ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 640ff8e577bSBrian Somers auth_Failure(r->cx.auth); 641ff8e577bSBrian Somers } else if (got == RAD_ACCESS_REJECT) 642ff8e577bSBrian Somers auth_Failure(r->cx.auth); 643ff8e577bSBrian Somers else { 644f0cdd9c0SBrian Somers r->valid = 1; 645f0cdd9c0SBrian Somers auth_Success(r->cx.auth); 646f0cdd9c0SBrian Somers } 647ff8e577bSBrian Somers rad_close(r->cx.rad); 648972a1bcfSBrian Somers } 649972a1bcfSBrian Somers 650f0cdd9c0SBrian Somers /* 6518e7bd08eSBrian Somers * We've either timed out or select()ed on the read descriptor 652f0cdd9c0SBrian Somers */ 653f0cdd9c0SBrian Somers static void 654f0cdd9c0SBrian Somers radius_Continue(struct radius *r, int sel) 655f0cdd9c0SBrian Somers { 656f0cdd9c0SBrian Somers struct timeval tv; 657f0cdd9c0SBrian Somers int got; 658972a1bcfSBrian Somers 659f0cdd9c0SBrian Somers timer_Stop(&r->cx.timer); 660f0cdd9c0SBrian Somers if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) { 661e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 662e715b13bSBrian Somers "Radius: Request re-sent\n"); 663f0cdd9c0SBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 664f0cdd9c0SBrian Somers timer_Start(&r->cx.timer); 665f0cdd9c0SBrian Somers return; 666f0cdd9c0SBrian Somers } 667f0cdd9c0SBrian Somers 668f0cdd9c0SBrian Somers radius_Process(r, got); 669f0cdd9c0SBrian Somers } 670f0cdd9c0SBrian Somers 671f0cdd9c0SBrian Somers /* 672f0cdd9c0SBrian Somers * Time to call rad_continue_send_request() - timed out. 673f0cdd9c0SBrian Somers */ 674f0cdd9c0SBrian Somers static void 675f0cdd9c0SBrian Somers radius_Timeout(void *v) 676f0cdd9c0SBrian Somers { 677f0cdd9c0SBrian Somers radius_Continue((struct radius *)v, 0); 678f0cdd9c0SBrian Somers } 679f0cdd9c0SBrian Somers 680f0cdd9c0SBrian Somers /* 681f0cdd9c0SBrian Somers * Time to call rad_continue_send_request() - something to read. 682f0cdd9c0SBrian Somers */ 683f0cdd9c0SBrian Somers static void 684057f1760SBrian Somers radius_Read(struct fdescriptor *d, struct bundle *bundle __unused, 685057f1760SBrian Somers const fd_set *fdset __unused) 686f0cdd9c0SBrian Somers { 687f0cdd9c0SBrian Somers radius_Continue(descriptor2radius(d), 1); 688f0cdd9c0SBrian Somers } 689f0cdd9c0SBrian Somers 690f0cdd9c0SBrian Somers /* 69188044778SBrian Somers * Flush any pending transactions 69288044778SBrian Somers */ 69388044778SBrian Somers void 69488044778SBrian Somers radius_Flush(struct radius *r) 69588044778SBrian Somers { 69688044778SBrian Somers struct timeval tv; 69788044778SBrian Somers fd_set s; 69888044778SBrian Somers 69988044778SBrian Somers while (r->cx.fd != -1) { 70088044778SBrian Somers FD_ZERO(&s); 70188044778SBrian Somers FD_SET(r->cx.fd, &s); 70288044778SBrian Somers tv.tv_sec = 0; 70388044778SBrian Somers tv.tv_usec = TICKUNIT; 70488044778SBrian Somers select(r->cx.fd + 1, &s, NULL, NULL, &tv); 70588044778SBrian Somers radius_Continue(r, 1); 70688044778SBrian Somers } 70788044778SBrian Somers } 70888044778SBrian Somers 70988044778SBrian Somers /* 7108e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 711f0cdd9c0SBrian Somers */ 712f0cdd9c0SBrian Somers static int 713057f1760SBrian Somers radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w __unused, 714057f1760SBrian Somers fd_set *e __unused, int *n) 715f0cdd9c0SBrian Somers { 716f0cdd9c0SBrian Somers struct radius *rad = descriptor2radius(d); 717f0cdd9c0SBrian Somers 718f0cdd9c0SBrian Somers if (r && rad->cx.fd != -1) { 719f0cdd9c0SBrian Somers FD_SET(rad->cx.fd, r); 720f0cdd9c0SBrian Somers if (*n < rad->cx.fd + 1) 721f0cdd9c0SBrian Somers *n = rad->cx.fd + 1; 722f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd); 72382d6780cSBrian Somers return 1; 724972a1bcfSBrian Somers } 725972a1bcfSBrian Somers 726f0cdd9c0SBrian Somers return 0; 727f0cdd9c0SBrian Somers } 728f0cdd9c0SBrian Somers 729f0cdd9c0SBrian Somers /* 7308e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 731f0cdd9c0SBrian Somers */ 732f0cdd9c0SBrian Somers static int 733f013f33eSBrian Somers radius_IsSet(struct fdescriptor *d, const fd_set *fdset) 734f0cdd9c0SBrian Somers { 735f0cdd9c0SBrian Somers struct radius *r = descriptor2radius(d); 736f0cdd9c0SBrian Somers 737f0cdd9c0SBrian Somers return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset); 738f0cdd9c0SBrian Somers } 739f0cdd9c0SBrian Somers 740f0cdd9c0SBrian Somers /* 7418e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 742f0cdd9c0SBrian Somers */ 743f0cdd9c0SBrian Somers static int 744057f1760SBrian Somers radius_Write(struct fdescriptor *d __unused, struct bundle *bundle __unused, 745057f1760SBrian Somers const fd_set *fdset __unused) 746f0cdd9c0SBrian Somers { 747f0cdd9c0SBrian Somers /* We never want to write here ! */ 748f0cdd9c0SBrian Somers log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n"); 749f0cdd9c0SBrian Somers return 0; 750f0cdd9c0SBrian Somers } 751f0cdd9c0SBrian Somers 752f0cdd9c0SBrian Somers /* 753f0cdd9c0SBrian Somers * Initialise ourselves 754f0cdd9c0SBrian Somers */ 755f0cdd9c0SBrian Somers void 756f0cdd9c0SBrian Somers radius_Init(struct radius *r) 757f0cdd9c0SBrian Somers { 758f0cdd9c0SBrian Somers r->desc.type = RADIUS_DESCRIPTOR; 759f0cdd9c0SBrian Somers r->desc.UpdateSet = radius_UpdateSet; 760f0cdd9c0SBrian Somers r->desc.IsSet = radius_IsSet; 761f0cdd9c0SBrian Somers r->desc.Read = radius_Read; 762f0cdd9c0SBrian Somers r->desc.Write = radius_Write; 763ff8e577bSBrian Somers r->cx.fd = -1; 764ff8e577bSBrian Somers r->cx.rad = NULL; 765f0cdd9c0SBrian Somers memset(&r->cx.timer, '\0', sizeof r->cx.timer); 766ff8e577bSBrian Somers r->cx.auth = NULL; 767ff8e577bSBrian Somers r->valid = 0; 768ff8e577bSBrian Somers r->vj = 0; 769ff8e577bSBrian Somers r->ip.s_addr = INADDR_ANY; 770ff8e577bSBrian Somers r->mask.s_addr = INADDR_NONE; 771ff8e577bSBrian Somers r->routes = NULL; 772ff8e577bSBrian Somers r->mtu = DEF_MTU; 773a16061b2SBrian Somers r->msrepstr = NULL; 774ff8e577bSBrian Somers r->repstr = NULL; 7750fe74aa4SHajimu UMEMOTO #ifndef NOINET6 776ec3e98b8SHajimu UMEMOTO r->ipv6prefix = NULL; 7770fe74aa4SHajimu UMEMOTO r->ipv6routes = NULL; 7780fe74aa4SHajimu UMEMOTO #endif 779ff8e577bSBrian Somers r->errstr = NULL; 7808fb5ef5aSBrian Somers r->mppe.policy = 0; 7818fb5ef5aSBrian Somers r->mppe.types = 0; 7828fb5ef5aSBrian Somers r->mppe.recvkey = NULL; 7838fb5ef5aSBrian Somers r->mppe.recvkeylen = 0; 7848fb5ef5aSBrian Somers r->mppe.sendkey = NULL; 7858fb5ef5aSBrian Somers r->mppe.sendkeylen = 0; 786ff8e577bSBrian Somers *r->cfg.file = '\0';; 787794c9bbcSBrian Somers log_Printf(LogDEBUG, "Radius: radius_Init\n"); 788f0cdd9c0SBrian Somers } 789f0cdd9c0SBrian Somers 790f0cdd9c0SBrian Somers /* 791f0cdd9c0SBrian Somers * Forget everything and go back to initialised state. 792f0cdd9c0SBrian Somers */ 793f0cdd9c0SBrian Somers void 794f0cdd9c0SBrian Somers radius_Destroy(struct radius *r) 795f0cdd9c0SBrian Somers { 796f0cdd9c0SBrian Somers r->valid = 0; 797794c9bbcSBrian Somers log_Printf(LogDEBUG, "Radius: radius_Destroy\n"); 798f0cdd9c0SBrian Somers timer_Stop(&r->cx.timer); 799f0cdd9c0SBrian Somers route_DeleteAll(&r->routes); 8000fe74aa4SHajimu UMEMOTO #ifndef NOINET6 8010fe74aa4SHajimu UMEMOTO route_DeleteAll(&r->ipv6routes); 8020fe74aa4SHajimu UMEMOTO #endif 803bf1eaec5SBrian Somers free(r->filterid); 804bf1eaec5SBrian Somers r->filterid = NULL; 805a16061b2SBrian Somers free(r->msrepstr); 806a16061b2SBrian Somers r->msrepstr = NULL; 807ff8e577bSBrian Somers free(r->repstr); 808ff8e577bSBrian Somers r->repstr = NULL; 809ec3e98b8SHajimu UMEMOTO #ifndef NOINET6 810ec3e98b8SHajimu UMEMOTO free(r->ipv6prefix); 811ec3e98b8SHajimu UMEMOTO r->ipv6prefix = NULL; 812ec3e98b8SHajimu UMEMOTO #endif 813ff8e577bSBrian Somers free(r->errstr); 814ff8e577bSBrian Somers r->errstr = NULL; 8158fb5ef5aSBrian Somers free(r->mppe.recvkey); 8168fb5ef5aSBrian Somers r->mppe.recvkey = NULL; 8178fb5ef5aSBrian Somers r->mppe.recvkeylen = 0; 8188fb5ef5aSBrian Somers free(r->mppe.sendkey); 8198fb5ef5aSBrian Somers r->mppe.sendkey = NULL; 8208fb5ef5aSBrian Somers r->mppe.sendkeylen = 0; 821f0cdd9c0SBrian Somers if (r->cx.fd != -1) { 822f0cdd9c0SBrian Somers r->cx.fd = -1; 823f0cdd9c0SBrian Somers rad_close(r->cx.rad); 824f0cdd9c0SBrian Somers } 825f0cdd9c0SBrian Somers } 826f0cdd9c0SBrian Somers 827de59e178SBrian Somers static int 828de59e178SBrian Somers radius_put_physical_details(struct rad_handle *rad, struct physical *p) 829de59e178SBrian Somers { 830de59e178SBrian Somers int slot, type; 831de59e178SBrian Somers 832de59e178SBrian Somers type = RAD_VIRTUAL; 833de59e178SBrian Somers if (p->handler) 834de59e178SBrian Somers switch (p->handler->type) { 835de59e178SBrian Somers case I4B_DEVICE: 836de59e178SBrian Somers type = RAD_ISDN_SYNC; 837de59e178SBrian Somers break; 838de59e178SBrian Somers 839de59e178SBrian Somers case TTY_DEVICE: 840de59e178SBrian Somers type = RAD_ASYNC; 841de59e178SBrian Somers break; 842de59e178SBrian Somers 843de59e178SBrian Somers case ETHER_DEVICE: 844de59e178SBrian Somers type = RAD_ETHERNET; 845de59e178SBrian Somers break; 846de59e178SBrian Somers 847de59e178SBrian Somers case TCP_DEVICE: 848de59e178SBrian Somers case UDP_DEVICE: 849de59e178SBrian Somers case EXEC_DEVICE: 850de59e178SBrian Somers case ATM_DEVICE: 851de59e178SBrian Somers case NG_DEVICE: 852de59e178SBrian Somers type = RAD_VIRTUAL; 853de59e178SBrian Somers break; 854de59e178SBrian Somers } 855de59e178SBrian Somers 856de59e178SBrian Somers if (rad_put_int(rad, RAD_NAS_PORT_TYPE, type) != 0) { 857de59e178SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad)); 858de59e178SBrian Somers rad_close(rad); 859de59e178SBrian Somers return 0; 860de59e178SBrian Somers } 861de59e178SBrian Somers 862de59e178SBrian Somers if ((slot = physical_Slot(p)) >= 0) 863de59e178SBrian Somers if (rad_put_int(rad, RAD_NAS_PORT, slot) != 0) { 864de59e178SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad)); 865de59e178SBrian Somers rad_close(rad); 866de59e178SBrian Somers return 0; 867de59e178SBrian Somers } 868de59e178SBrian Somers 869de59e178SBrian Somers return 1; 870de59e178SBrian Somers } 871de59e178SBrian Somers 872f0cdd9c0SBrian Somers /* 873f0cdd9c0SBrian Somers * Start an authentication request to the RADIUS server. 874f0cdd9c0SBrian Somers */ 875a16061b2SBrian Somers int 876f0cdd9c0SBrian Somers radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, 877a16061b2SBrian Somers const char *key, int klen, const char *nchallenge, 878250be50bSBrian Somers int nclen) 879f0cdd9c0SBrian Somers { 88026e6a622SBrian Somers char hostname[MAXHOSTNAMELEN]; 881057f1760SBrian Somers struct timeval tv; 882057f1760SBrian Somers const char *what = "questionable"; /* silence warnings! */ 883057f1760SBrian Somers char *mac_addr; 884057f1760SBrian Somers int got; 885f10f5203SBrian Somers struct hostent *hp; 886f10f5203SBrian Somers struct in_addr hostaddr; 887ff8e577bSBrian Somers #ifndef NODES 888a16061b2SBrian Somers struct mschap_response msresp; 889a16061b2SBrian Somers struct mschap2_response msresp2; 890250be50bSBrian Somers const struct MSCHAPv2_resp *keyv2; 891ff8e577bSBrian Somers #endif 892f0cdd9c0SBrian Somers 893f0cdd9c0SBrian Somers if (!*r->cfg.file) 894a16061b2SBrian Somers return 0; 895f0cdd9c0SBrian Somers 896f0cdd9c0SBrian Somers if (r->cx.fd != -1) 897f0cdd9c0SBrian Somers /* 898f0cdd9c0SBrian Somers * We assume that our name/key/challenge is the same as last time, 899f0cdd9c0SBrian Somers * and just continue to wait for the RADIUS server(s). 900f0cdd9c0SBrian Somers */ 901a16061b2SBrian Somers return 1; 902f0cdd9c0SBrian Somers 903f0cdd9c0SBrian Somers radius_Destroy(r); 904f0cdd9c0SBrian Somers 905794c9bbcSBrian Somers if ((r->cx.rad = rad_auth_open()) == NULL) { 906794c9bbcSBrian Somers log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 907a16061b2SBrian Somers return 0; 908f0cdd9c0SBrian Somers } 909f0cdd9c0SBrian Somers 910f0cdd9c0SBrian Somers if (rad_config(r->cx.rad, r->cfg.file) != 0) { 911f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 912f0cdd9c0SBrian Somers rad_close(r->cx.rad); 913a16061b2SBrian Somers return 0; 914f0cdd9c0SBrian Somers } 915f0cdd9c0SBrian Somers 916f0cdd9c0SBrian Somers if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) { 917f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 918f0cdd9c0SBrian Somers rad_close(r->cx.rad); 919a16061b2SBrian Somers return 0; 920f0cdd9c0SBrian Somers } 921f0cdd9c0SBrian Somers 9224dc4e1eeSBrian Somers if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 || 923f0cdd9c0SBrian Somers rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 924f0cdd9c0SBrian Somers rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 925f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 926f0cdd9c0SBrian Somers rad_close(r->cx.rad); 927a16061b2SBrian Somers return 0; 928f0cdd9c0SBrian Somers } 929f0cdd9c0SBrian Somers 930ff8e577bSBrian Somers switch (authp->physical->link.lcp.want_auth) { 931ff8e577bSBrian Somers case PROTO_PAP: 932ff8e577bSBrian Somers /* We're talking PAP */ 933ff8e577bSBrian Somers if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) { 934ff8e577bSBrian Somers log_Printf(LogERROR, "PAP: rad_put_string: %s\n", 935ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 936ff8e577bSBrian Somers rad_close(r->cx.rad); 937a16061b2SBrian Somers return 0; 938ff8e577bSBrian Somers } 939e715b13bSBrian Somers what = "PAP"; 940ff8e577bSBrian Somers break; 941ff8e577bSBrian Somers 942ff8e577bSBrian Somers case PROTO_CHAP: 943ff8e577bSBrian Somers switch (authp->physical->link.lcp.want_authtype) { 944ff8e577bSBrian Somers case 0x5: 94550ca6ec3SBrian Somers if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 || 946a16061b2SBrian Somers rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) { 947f0cdd9c0SBrian Somers log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", 948f0cdd9c0SBrian Somers rad_strerror(r->cx.rad)); 949f0cdd9c0SBrian Somers rad_close(r->cx.rad); 950a16061b2SBrian Somers return 0; 951f0cdd9c0SBrian Somers } 952e715b13bSBrian Somers what = "CHAP"; 953ff8e577bSBrian Somers break; 954ff8e577bSBrian Somers 955ff8e577bSBrian Somers #ifndef NODES 956ff8e577bSBrian Somers case 0x80: 957ff8e577bSBrian Somers if (klen != 50) { 958a16061b2SBrian Somers log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen); 959f0cdd9c0SBrian Somers rad_close(r->cx.rad); 960a16061b2SBrian Somers return 0; 961f0cdd9c0SBrian Somers } 962a16061b2SBrian Somers 963ff8e577bSBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 964a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 965a16061b2SBrian Somers msresp.ident = *key; 966a16061b2SBrian Somers msresp.flags = 0x01; 967a16061b2SBrian Somers memcpy(msresp.lm_response, key + 1, 24); 968a16061b2SBrian Somers memcpy(msresp.nt_response, key + 25, 24); 969ff8e577bSBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 970a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp, 971a16061b2SBrian Somers sizeof msresp); 972e715b13bSBrian Somers what = "MSCHAP"; 973ff8e577bSBrian Somers break; 974ff8e577bSBrian Somers 975ff8e577bSBrian Somers case 0x81: 976250be50bSBrian Somers if (klen != sizeof(*keyv2) + 1) { 977a16061b2SBrian Somers log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen); 978a16061b2SBrian Somers rad_close(r->cx.rad); 979a16061b2SBrian Somers return 0; 980a16061b2SBrian Somers } 981a16061b2SBrian Somers 982250be50bSBrian Somers keyv2 = (const struct MSCHAPv2_resp *)(key + 1); 983a16061b2SBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 984a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 985a16061b2SBrian Somers msresp2.ident = *key; 986250be50bSBrian Somers msresp2.flags = keyv2->Flags; 987250be50bSBrian Somers memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response); 988a16061b2SBrian Somers memset(msresp2.reserved, '\0', sizeof msresp2.reserved); 989250be50bSBrian Somers memcpy(msresp2.pchallenge, keyv2->PeerChallenge, 990250be50bSBrian Somers sizeof msresp2.pchallenge); 991a16061b2SBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 992a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2, 993a16061b2SBrian Somers sizeof msresp2); 994e715b13bSBrian Somers what = "MSCHAPv2"; 995a16061b2SBrian Somers break; 996ff8e577bSBrian Somers #endif 997ff8e577bSBrian Somers default: 998ff8e577bSBrian Somers log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n", 999ff8e577bSBrian Somers authp->physical->link.lcp.want_authtype); 1000ff8e577bSBrian Somers rad_close(r->cx.rad); 1001a16061b2SBrian Somers return 0; 1002ff8e577bSBrian Somers } 1003ff8e577bSBrian Somers } 1004f0cdd9c0SBrian Somers 1005f10f5203SBrian Somers if (gethostname(hostname, sizeof hostname) != 0) 1006f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 1007f10f5203SBrian Somers else { 10080508c09aSBrian Somers if (Enabled(authp->physical->dl->bundle, OPT_NAS_IP_ADDRESS) && 10090508c09aSBrian Somers (hp = gethostbyname(hostname)) != NULL) { 1010f10f5203SBrian Somers hostaddr.s_addr = *(u_long *)hp->h_addr; 1011f10f5203SBrian Somers if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 1012f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1013f10f5203SBrian Somers rad_strerror(r->cx.rad)); 1014f10f5203SBrian Somers rad_close(r->cx.rad); 1015a16061b2SBrian Somers return 0; 1016f10f5203SBrian Somers } 1017f10f5203SBrian Somers } 10180508c09aSBrian Somers if (Enabled(authp->physical->dl->bundle, OPT_NAS_IDENTIFIER) && 10190508c09aSBrian Somers rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 1020f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1021f10f5203SBrian Somers rad_strerror(r->cx.rad)); 1022f10f5203SBrian Somers rad_close(r->cx.rad); 1023a16061b2SBrian Somers return 0; 1024f10f5203SBrian Somers } 1025f10f5203SBrian Somers } 1026f10f5203SBrian Somers 10275de776b9SBrian Somers if ((mac_addr = getenv("HISMACADDR")) != NULL && 10285de776b9SBrian Somers rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) { 10295de776b9SBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 10305de776b9SBrian Somers rad_close(r->cx.rad); 1031057f1760SBrian Somers return 0; 10325de776b9SBrian Somers } 10335de776b9SBrian Somers 1034de59e178SBrian Somers radius_put_physical_details(r->cx.rad, authp->physical); 1035f10f5203SBrian Somers 1036e715b13bSBrian Somers log_Printf(LogRADIUS, "Radius(auth): %s data sent for %s\n", what, name); 1037e715b13bSBrian Somers 1038c42627ffSBrian Somers r->cx.auth = authp; 1039f0cdd9c0SBrian Somers if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 1040f0cdd9c0SBrian Somers radius_Process(r, got); 1041f0cdd9c0SBrian Somers else { 1042e715b13bSBrian Somers log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE, 1043e715b13bSBrian Somers "Radius: Request sent\n"); 1044f0cdd9c0SBrian Somers log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 1045f0cdd9c0SBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 1046f0cdd9c0SBrian Somers r->cx.timer.func = radius_Timeout; 1047c42627ffSBrian Somers r->cx.timer.name = "radius auth"; 1048f0cdd9c0SBrian Somers r->cx.timer.arg = r; 1049f0cdd9c0SBrian Somers timer_Start(&r->cx.timer); 1050f0cdd9c0SBrian Somers } 1051a16061b2SBrian Somers 1052a16061b2SBrian Somers return 1; 1053f0cdd9c0SBrian Somers } 1054f0cdd9c0SBrian Somers 1055cf7c10d0SHajimu UMEMOTO /* Fetch IP, netmask from IPCP */ 1056cf7c10d0SHajimu UMEMOTO void 1057cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ip(struct radacct *ac, struct in_addr *peer_ip, 1058cf7c10d0SHajimu UMEMOTO struct in_addr *netmask) 1059cf7c10d0SHajimu UMEMOTO { 1060cf7c10d0SHajimu UMEMOTO ac->proto = PROTO_IPCP; 10612cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ip.addr, peer_ip, sizeof(ac->peer.ip.addr)); 10622cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ip.mask, netmask, sizeof(ac->peer.ip.mask)); 1063cf7c10d0SHajimu UMEMOTO } 1064cf7c10d0SHajimu UMEMOTO 1065cf7c10d0SHajimu UMEMOTO #ifndef NOINET6 1066cf7c10d0SHajimu UMEMOTO /* Fetch interface-id from IPV6CP */ 1067cf7c10d0SHajimu UMEMOTO void 1068cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ipv6(struct radacct *ac, u_char *ifid) 1069cf7c10d0SHajimu UMEMOTO { 1070cf7c10d0SHajimu UMEMOTO ac->proto = PROTO_IPV6CP; 10712cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ipv6.ifid, ifid, sizeof(ac->peer.ipv6.ifid)); 1072cf7c10d0SHajimu UMEMOTO } 1073cf7c10d0SHajimu UMEMOTO #endif 1074cf7c10d0SHajimu UMEMOTO 1075f0cdd9c0SBrian Somers /* 1076794c9bbcSBrian Somers * Send an accounting request to the RADIUS server 1077794c9bbcSBrian Somers */ 1078794c9bbcSBrian Somers void 1079794c9bbcSBrian Somers radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl, 1080cf7c10d0SHajimu UMEMOTO int acct_type, struct pppThroughput *stats) 1081794c9bbcSBrian Somers { 1082794c9bbcSBrian Somers struct timeval tv; 1083de59e178SBrian Somers int got; 108426e6a622SBrian Somers char hostname[MAXHOSTNAMELEN]; 10855de776b9SBrian Somers char *mac_addr; 1086794c9bbcSBrian Somers struct hostent *hp; 1087794c9bbcSBrian Somers struct in_addr hostaddr; 1088794c9bbcSBrian Somers 1089794c9bbcSBrian Somers if (!*r->cfg.file) 1090794c9bbcSBrian Somers return; 1091794c9bbcSBrian Somers 1092794c9bbcSBrian Somers if (r->cx.fd != -1) 1093794c9bbcSBrian Somers /* 1094794c9bbcSBrian Somers * We assume that our name/key/challenge is the same as last time, 1095794c9bbcSBrian Somers * and just continue to wait for the RADIUS server(s). 1096794c9bbcSBrian Somers */ 1097794c9bbcSBrian Somers return; 1098794c9bbcSBrian Somers 10998fb5ef5aSBrian Somers timer_Stop(&r->cx.timer); 1100794c9bbcSBrian Somers 1101ba093e81SBrian Somers if ((r->cx.rad = rad_acct_open()) == NULL) { 1102794c9bbcSBrian Somers log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 1103794c9bbcSBrian Somers return; 1104794c9bbcSBrian Somers } 1105794c9bbcSBrian Somers 1106794c9bbcSBrian Somers if (rad_config(r->cx.rad, r->cfg.file) != 0) { 1107794c9bbcSBrian Somers log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 1108794c9bbcSBrian Somers rad_close(r->cx.rad); 1109794c9bbcSBrian Somers return; 1110794c9bbcSBrian Somers } 1111794c9bbcSBrian Somers 1112794c9bbcSBrian Somers if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) { 1113794c9bbcSBrian Somers log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 1114794c9bbcSBrian Somers rad_close(r->cx.rad); 1115794c9bbcSBrian Somers return; 1116794c9bbcSBrian Somers } 1117794c9bbcSBrian Somers 1118794c9bbcSBrian Somers /* Grab some accounting data and initialize structure */ 1119794c9bbcSBrian Somers if (acct_type == RAD_START) { 1120794c9bbcSBrian Somers ac->rad_parent = r; 1121794c9bbcSBrian Somers /* Fetch username from datalink */ 11224dc4e1eeSBrian Somers strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name); 1123794c9bbcSBrian Somers ac->user_name[AUTHLEN-1] = '\0'; 1124794c9bbcSBrian Somers 1125794c9bbcSBrian Somers ac->authentic = 2; /* Assume RADIUS verified auth data */ 1126794c9bbcSBrian Somers 1127794c9bbcSBrian Somers /* Generate a session ID */ 112812b5aabaSBrian Somers snprintf(ac->session_id, sizeof ac->session_id, "%s%ld-%s%lu", 112912b5aabaSBrian Somers dl->bundle->cfg.auth.name, (long)getpid(), 11304dc4e1eeSBrian Somers dl->peer.authname, (unsigned long)stats->uptime); 1131794c9bbcSBrian Somers 1132794c9bbcSBrian Somers /* And grab our MP socket name */ 1133794c9bbcSBrian Somers snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s", 1134794c9bbcSBrian Somers dl->bundle->ncp.mp.active ? 1135794c9bbcSBrian Somers dl->bundle->ncp.mp.server.socket.sun_path : ""); 1136794c9bbcSBrian Somers }; 1137794c9bbcSBrian Somers 1138794c9bbcSBrian Somers if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 || 1139794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 1140cf7c10d0SHajimu UMEMOTO rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 1141794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1142794c9bbcSBrian Somers rad_close(r->cx.rad); 1143794c9bbcSBrian Somers return; 1144794c9bbcSBrian Somers } 1145cf7c10d0SHajimu UMEMOTO switch (ac->proto) { 1146cf7c10d0SHajimu UMEMOTO case PROTO_IPCP: 11472cc2a59dSHajimu UMEMOTO if (rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS, 11487cbe2606SBrian Somers ac->peer.ip.addr) != 0 || 11492cc2a59dSHajimu UMEMOTO rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK, 11502cc2a59dSHajimu UMEMOTO ac->peer.ip.mask) != 0) { 1151cf7c10d0SHajimu UMEMOTO log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1152cf7c10d0SHajimu UMEMOTO rad_close(r->cx.rad); 1153cf7c10d0SHajimu UMEMOTO return; 1154cf7c10d0SHajimu UMEMOTO } 1155cf7c10d0SHajimu UMEMOTO break; 1156cf7c10d0SHajimu UMEMOTO #ifndef NOINET6 1157cf7c10d0SHajimu UMEMOTO case PROTO_IPV6CP: 11582cc2a59dSHajimu UMEMOTO if (rad_put_attr(r->cx.rad, RAD_FRAMED_INTERFACE_ID, ac->peer.ipv6.ifid, 11592cc2a59dSHajimu UMEMOTO sizeof(ac->peer.ipv6.ifid)) != 0) { 1160cf7c10d0SHajimu UMEMOTO log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad)); 1161cf7c10d0SHajimu UMEMOTO rad_close(r->cx.rad); 1162cf7c10d0SHajimu UMEMOTO return; 1163cf7c10d0SHajimu UMEMOTO } 1164ec3e98b8SHajimu UMEMOTO if (r->ipv6prefix) { 1165ec3e98b8SHajimu UMEMOTO /* 1166ec3e98b8SHajimu UMEMOTO * Since PPP doesn't delegate an IPv6 prefix to a peer, 1167ec3e98b8SHajimu UMEMOTO * Framed-IPv6-Prefix may be not used, actually. 1168ec3e98b8SHajimu UMEMOTO */ 1169ec3e98b8SHajimu UMEMOTO if (rad_put_attr(r->cx.rad, RAD_FRAMED_IPV6_PREFIX, r->ipv6prefix, 1170ec3e98b8SHajimu UMEMOTO sizeof(struct in6_addr) + 2) != 0) { 1171ec3e98b8SHajimu UMEMOTO log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad)); 1172ec3e98b8SHajimu UMEMOTO rad_close(r->cx.rad); 1173ec3e98b8SHajimu UMEMOTO return; 1174ec3e98b8SHajimu UMEMOTO } 1175ec3e98b8SHajimu UMEMOTO } 1176cf7c10d0SHajimu UMEMOTO break; 1177cf7c10d0SHajimu UMEMOTO #endif 1178cf7c10d0SHajimu UMEMOTO default: 1179cf7c10d0SHajimu UMEMOTO /* We don't log any protocol specific information */ 1180cf7c10d0SHajimu UMEMOTO break; 1181cf7c10d0SHajimu UMEMOTO } 1182794c9bbcSBrian Somers 11835de776b9SBrian Somers if ((mac_addr = getenv("HISMACADDR")) != NULL && 11845de776b9SBrian Somers rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) { 11855de776b9SBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 11865de776b9SBrian Somers rad_close(r->cx.rad); 11875de776b9SBrian Somers return; 11885de776b9SBrian Somers } 11895de776b9SBrian Somers 1190794c9bbcSBrian Somers if (gethostname(hostname, sizeof hostname) != 0) 1191794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 1192794c9bbcSBrian Somers else { 11930508c09aSBrian Somers if (Enabled(dl->bundle, OPT_NAS_IP_ADDRESS) && 11940508c09aSBrian Somers (hp = gethostbyname(hostname)) != NULL) { 1195794c9bbcSBrian Somers hostaddr.s_addr = *(u_long *)hp->h_addr; 1196794c9bbcSBrian Somers if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 1197794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1198794c9bbcSBrian Somers rad_strerror(r->cx.rad)); 1199794c9bbcSBrian Somers rad_close(r->cx.rad); 1200794c9bbcSBrian Somers return; 1201794c9bbcSBrian Somers } 1202794c9bbcSBrian Somers } 12030508c09aSBrian Somers if (Enabled(dl->bundle, OPT_NAS_IDENTIFIER) && 12040508c09aSBrian Somers rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 1205794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1206794c9bbcSBrian Somers rad_strerror(r->cx.rad)); 1207794c9bbcSBrian Somers rad_close(r->cx.rad); 1208794c9bbcSBrian Somers return; 1209794c9bbcSBrian Somers } 1210794c9bbcSBrian Somers } 1211794c9bbcSBrian Somers 1212de59e178SBrian Somers radius_put_physical_details(r->cx.rad, dl->physical); 1213794c9bbcSBrian Somers 1214794c9bbcSBrian Somers if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 || 1215794c9bbcSBrian Somers rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 || 1216794c9bbcSBrian Somers rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID, 1217794c9bbcSBrian Somers ac->multi_session_id) != 0 || 1218794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) { 1219794c9bbcSBrian Somers /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */ 1220794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1221794c9bbcSBrian Somers rad_close(r->cx.rad); 1222794c9bbcSBrian Somers return; 1223794c9bbcSBrian Somers } 1224794c9bbcSBrian Somers 1225e715b13bSBrian Somers if (acct_type == RAD_STOP || acct_type == RAD_ALIVE) 1226794c9bbcSBrian Somers /* Show some statistics */ 1227dfb3194aSDiomidis Spinellis if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn % UINT32_MAX) != 0 || 1228dfb3194aSDiomidis Spinellis rad_put_int(r->cx.rad, RAD_ACCT_INPUT_GIGAWORDS, stats->OctetsIn / UINT32_MAX) != 0 || 1229794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 || 1230dfb3194aSDiomidis Spinellis rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut % UINT32_MAX) != 0 || 1231dfb3194aSDiomidis Spinellis rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_GIGAWORDS, stats->OctetsOut / UINT32_MAX) != 0 || 1232794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut) 1233794c9bbcSBrian Somers != 0 || 1234794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats)) 1235794c9bbcSBrian Somers != 0) { 1236794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1237794c9bbcSBrian Somers rad_close(r->cx.rad); 1238794c9bbcSBrian Somers return; 1239794c9bbcSBrian Somers } 1240794c9bbcSBrian Somers 1241e715b13bSBrian Somers if (log_IsKept(LogPHASE) || log_IsKept(LogRADIUS)) { 1242057f1760SBrian Somers const char *what; 1243e715b13bSBrian Somers int level; 1244e715b13bSBrian Somers 1245e715b13bSBrian Somers switch (acct_type) { 1246e715b13bSBrian Somers case RAD_START: 1247e715b13bSBrian Somers what = "START"; 1248e715b13bSBrian Somers level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1249e715b13bSBrian Somers break; 1250e715b13bSBrian Somers case RAD_STOP: 1251e715b13bSBrian Somers what = "STOP"; 1252e715b13bSBrian Somers level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1253e715b13bSBrian Somers break; 1254e715b13bSBrian Somers case RAD_ALIVE: 1255e715b13bSBrian Somers what = "ALIVE"; 1256e715b13bSBrian Somers level = LogRADIUS; 1257e715b13bSBrian Somers break; 1258e715b13bSBrian Somers default: 1259e715b13bSBrian Somers what = "<unknown>"; 1260e715b13bSBrian Somers level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS; 1261e715b13bSBrian Somers break; 1262e715b13bSBrian Somers } 1263e715b13bSBrian Somers log_Printf(level, "Radius(acct): %s data sent\n", what); 1264e715b13bSBrian Somers } 1265e715b13bSBrian Somers 1266c42627ffSBrian Somers r->cx.auth = NULL; /* Not valid for accounting requests */ 1267794c9bbcSBrian Somers if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 1268794c9bbcSBrian Somers radius_Process(r, got); 1269794c9bbcSBrian Somers else { 1270794c9bbcSBrian Somers log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 1271794c9bbcSBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 1272794c9bbcSBrian Somers r->cx.timer.func = radius_Timeout; 1273c42627ffSBrian Somers r->cx.timer.name = "radius acct"; 1274794c9bbcSBrian Somers r->cx.timer.arg = r; 1275794c9bbcSBrian Somers timer_Start(&r->cx.timer); 1276794c9bbcSBrian Somers } 1277794c9bbcSBrian Somers } 1278794c9bbcSBrian Somers 1279794c9bbcSBrian Somers /* 1280f0cdd9c0SBrian Somers * How do things look at the moment ? 1281f0cdd9c0SBrian Somers */ 1282972a1bcfSBrian Somers void 1283972a1bcfSBrian Somers radius_Show(struct radius *r, struct prompt *p) 1284972a1bcfSBrian Somers { 128574457d3dSBrian Somers prompt_Printf(p, " Radius config: %s", 128674457d3dSBrian Somers *r->cfg.file ? r->cfg.file : "none"); 1287972a1bcfSBrian Somers if (r->valid) { 1288972a1bcfSBrian Somers prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip)); 1289972a1bcfSBrian Somers prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask)); 1290972a1bcfSBrian Somers prompt_Printf(p, " MTU: %lu\n", r->mtu); 1291972a1bcfSBrian Somers prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis"); 1292ff8e577bSBrian Somers prompt_Printf(p, " Message: %s\n", r->repstr ? r->repstr : ""); 12938fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Enc Policy: %s\n", 12948fb5ef5aSBrian Somers radius_policyname(r->mppe.policy)); 12958fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Enc Types: %s\n", 12968fb5ef5aSBrian Somers radius_typesname(r->mppe.types)); 12978fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Recv Key: %seceived\n", 12988fb5ef5aSBrian Somers r->mppe.recvkey ? "R" : "Not r"); 12998fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Send Key: %seceived\n", 13008fb5ef5aSBrian Somers r->mppe.sendkey ? "R" : "Not r"); 1301a16061b2SBrian Somers prompt_Printf(p, " MS-CHAP2-Response: %s\n", 1302a16061b2SBrian Somers r->msrepstr ? r->msrepstr : ""); 1303ff8e577bSBrian Somers prompt_Printf(p, " Error Message: %s\n", r->errstr ? r->errstr : ""); 1304972a1bcfSBrian Somers if (r->routes) 1305972a1bcfSBrian Somers route_ShowSticky(p, r->routes, " Routes", 16); 13060fe74aa4SHajimu UMEMOTO #ifndef NOINET6 13070fe74aa4SHajimu UMEMOTO if (r->ipv6routes) 13080fe74aa4SHajimu UMEMOTO route_ShowSticky(p, r->ipv6routes, " IPv6 Routes", 16); 13090fe74aa4SHajimu UMEMOTO #endif 1310972a1bcfSBrian Somers } else 1311972a1bcfSBrian Somers prompt_Printf(p, " (not authenticated)\n"); 1312972a1bcfSBrian Somers } 1313e715b13bSBrian Somers 1314e715b13bSBrian Somers static void 1315e715b13bSBrian Somers radius_alive(void *v) 1316e715b13bSBrian Somers { 1317e715b13bSBrian Somers struct bundle *bundle = (struct bundle *)v; 1318e715b13bSBrian Somers 1319e715b13bSBrian Somers timer_Stop(&bundle->radius.alive.timer); 1320e715b13bSBrian Somers bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS; 1321e715b13bSBrian Somers if (bundle->radius.alive.timer.load) { 1322e715b13bSBrian Somers radius_Account(&bundle->radius, &bundle->radacct, 1323e715b13bSBrian Somers bundle->links, RAD_ALIVE, &bundle->ncp.ipcp.throughput); 1324e715b13bSBrian Somers timer_Start(&bundle->radius.alive.timer); 1325e715b13bSBrian Somers } 1326e715b13bSBrian Somers } 1327e715b13bSBrian Somers 1328e715b13bSBrian Somers void 1329e715b13bSBrian Somers radius_StartTimer(struct bundle *bundle) 1330e715b13bSBrian Somers { 1331e715b13bSBrian Somers if (bundle->radius.cfg.file && bundle->radius.alive.interval) { 1332e715b13bSBrian Somers bundle->radius.alive.timer.func = radius_alive; 1333e715b13bSBrian Somers bundle->radius.alive.timer.name = "radius alive"; 1334e715b13bSBrian Somers bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS; 1335e715b13bSBrian Somers bundle->radius.alive.timer.arg = bundle; 1336e715b13bSBrian Somers radius_alive(bundle); 1337e715b13bSBrian Somers } 1338e715b13bSBrian Somers } 1339e715b13bSBrian Somers 1340e715b13bSBrian Somers void 1341e715b13bSBrian Somers radius_StopTimer(struct radius *r) 1342e715b13bSBrian Somers { 1343e715b13bSBrian Somers timer_Stop(&r->alive.timer); 1344e715b13bSBrian Somers } 1345