1972a1bcfSBrian Somers /* 2972a1bcfSBrian Somers * Copyright 1999 Internet Business Solutions Ltd., Switzerland 3972a1bcfSBrian Somers * All rights reserved. 4972a1bcfSBrian Somers * 5972a1bcfSBrian Somers * Redistribution and use in source and binary forms, with or without 6972a1bcfSBrian Somers * modification, are permitted provided that the following conditions 7972a1bcfSBrian Somers * are met: 8972a1bcfSBrian Somers * 1. Redistributions of source code must retain the above copyright 9972a1bcfSBrian Somers * notice, this list of conditions and the following disclaimer. 10972a1bcfSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 11972a1bcfSBrian Somers * notice, this list of conditions and the following disclaimer in the 12972a1bcfSBrian Somers * documentation and/or other materials provided with the distribution. 13972a1bcfSBrian Somers * 14972a1bcfSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15972a1bcfSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16972a1bcfSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17972a1bcfSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18972a1bcfSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19972a1bcfSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20972a1bcfSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21972a1bcfSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22972a1bcfSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23972a1bcfSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24972a1bcfSBrian Somers * SUCH DAMAGE. 25972a1bcfSBrian Somers * 2697d92980SPeter Wemm * $FreeBSD$ 27972a1bcfSBrian Somers * 28972a1bcfSBrian Somers */ 29972a1bcfSBrian Somers 30972a1bcfSBrian Somers #include <sys/param.h> 318fb5ef5aSBrian Somers 326b457978SBrian Somers #include <sys/socket.h> 33972a1bcfSBrian Somers #include <netinet/in_systm.h> 34972a1bcfSBrian Somers #include <netinet/in.h> 35972a1bcfSBrian Somers #include <netinet/ip.h> 36972a1bcfSBrian Somers #include <arpa/inet.h> 37972a1bcfSBrian Somers #include <sys/un.h> 386b457978SBrian Somers #include <net/route.h> 39972a1bcfSBrian Somers 4010e629b9SBrian Somers #ifdef LOCALRAD 4110e629b9SBrian Somers #include "radlib.h" 42ff8e577bSBrian Somers #include "radlib_vs.h" 4310e629b9SBrian Somers #else 44972a1bcfSBrian Somers #include <radlib.h> 45ff8e577bSBrian Somers #include <radlib_vs.h> 4610e629b9SBrian Somers #endif 4710e629b9SBrian Somers 4810e629b9SBrian Somers #include <errno.h> 498fb5ef5aSBrian Somers #ifndef NODES 508fb5ef5aSBrian Somers #include <md5.h> 518fb5ef5aSBrian Somers #endif 526eafd353SBrian Somers #include <stdarg.h> 53972a1bcfSBrian Somers #include <stdio.h> 54972a1bcfSBrian Somers #include <stdlib.h> 55972a1bcfSBrian Somers #include <string.h> 56f0cdd9c0SBrian Somers #include <sys/time.h> 57972a1bcfSBrian Somers #include <termios.h> 58f10f5203SBrian Somers #include <unistd.h> 59f10f5203SBrian Somers #include <netdb.h> 60972a1bcfSBrian Somers 615d9e6103SBrian Somers #include "layer.h" 62972a1bcfSBrian Somers #include "defs.h" 63972a1bcfSBrian Somers #include "log.h" 64972a1bcfSBrian Somers #include "descriptor.h" 65972a1bcfSBrian Somers #include "prompt.h" 66972a1bcfSBrian Somers #include "timer.h" 67972a1bcfSBrian Somers #include "fsm.h" 68972a1bcfSBrian Somers #include "iplist.h" 69972a1bcfSBrian Somers #include "slcompress.h" 70972a1bcfSBrian Somers #include "throughput.h" 71972a1bcfSBrian Somers #include "lqr.h" 72972a1bcfSBrian Somers #include "hdlc.h" 73972a1bcfSBrian Somers #include "mbuf.h" 7430949fd4SBrian Somers #include "ncpaddr.h" 7530949fd4SBrian Somers #include "ip.h" 76972a1bcfSBrian Somers #include "ipcp.h" 7730949fd4SBrian Somers #include "ipv6cp.h" 78972a1bcfSBrian Somers #include "route.h" 79972a1bcfSBrian Somers #include "command.h" 80972a1bcfSBrian Somers #include "filter.h" 81972a1bcfSBrian Somers #include "lcp.h" 82972a1bcfSBrian Somers #include "ccp.h" 83972a1bcfSBrian Somers #include "link.h" 84972a1bcfSBrian Somers #include "mp.h" 85972a1bcfSBrian Somers #include "radius.h" 86f0cdd9c0SBrian Somers #include "auth.h" 87f0cdd9c0SBrian Somers #include "async.h" 88f0cdd9c0SBrian Somers #include "physical.h" 89f0cdd9c0SBrian Somers #include "chat.h" 90f0cdd9c0SBrian Somers #include "cbcp.h" 91f0cdd9c0SBrian Somers #include "chap.h" 92f0cdd9c0SBrian Somers #include "datalink.h" 9330949fd4SBrian Somers #include "ncp.h" 94972a1bcfSBrian Somers #include "bundle.h" 95ff8e577bSBrian Somers #include "proto.h" 96ff8e577bSBrian Somers 97ff8e577bSBrian Somers #ifndef NODES 98a16061b2SBrian Somers struct mschap_response { 99ff8e577bSBrian Somers u_char ident; 100ff8e577bSBrian Somers u_char flags; 101ff8e577bSBrian Somers u_char lm_response[24]; 102ff8e577bSBrian Somers u_char nt_response[24]; 103ff8e577bSBrian Somers }; 104a16061b2SBrian Somers 105a16061b2SBrian Somers struct mschap2_response { 106a16061b2SBrian Somers u_char ident; 107a16061b2SBrian Somers u_char flags; 108a16061b2SBrian Somers u_char pchallenge[16]; 109a16061b2SBrian Somers u_char reserved[8]; 110a16061b2SBrian Somers u_char response[24]; 111a16061b2SBrian Somers }; 1128fb5ef5aSBrian Somers 1138fb5ef5aSBrian Somers #define AUTH_LEN 16 1148fb5ef5aSBrian Somers #define SALT_LEN 2 1158fb5ef5aSBrian Somers #endif 1168fb5ef5aSBrian Somers 1178fb5ef5aSBrian Somers static const char * 1188fb5ef5aSBrian Somers radius_policyname(int policy) 1198fb5ef5aSBrian Somers { 1208fb5ef5aSBrian Somers switch(policy) { 1218fb5ef5aSBrian Somers case MPPE_POLICY_ALLOWED: 1228fb5ef5aSBrian Somers return "Allowed"; 1238fb5ef5aSBrian Somers case MPPE_POLICY_REQUIRED: 1248fb5ef5aSBrian Somers return "Required"; 1258fb5ef5aSBrian Somers } 1268fb5ef5aSBrian Somers return NumStr(policy, NULL, 0); 1278fb5ef5aSBrian Somers } 1288fb5ef5aSBrian Somers 1298fb5ef5aSBrian Somers static const char * 1308fb5ef5aSBrian Somers radius_typesname(int types) 1318fb5ef5aSBrian Somers { 1328fb5ef5aSBrian Somers switch(types) { 1338fb5ef5aSBrian Somers case MPPE_TYPE_40BIT: 1348fb5ef5aSBrian Somers return "40 bit"; 1358fb5ef5aSBrian Somers case MPPE_TYPE_128BIT: 1368fb5ef5aSBrian Somers return "128 bit"; 1378fb5ef5aSBrian Somers case MPPE_TYPE_40BIT|MPPE_TYPE_128BIT: 1388fb5ef5aSBrian Somers return "40 or 128 bit"; 1398fb5ef5aSBrian Somers } 1408fb5ef5aSBrian Somers return NumStr(types, NULL, 0); 1418fb5ef5aSBrian Somers } 1428fb5ef5aSBrian Somers 1438fb5ef5aSBrian Somers #ifndef NODES 1448fb5ef5aSBrian Somers static void 1458fb5ef5aSBrian Somers demangle(struct radius *r, const void *mangled, size_t mlen, 1468fb5ef5aSBrian Somers char **buf, size_t *len) 1478fb5ef5aSBrian Somers { 1488fb5ef5aSBrian Somers char R[AUTH_LEN]; /* variable names as per rfc2548 */ 1498fb5ef5aSBrian Somers const char *S; 1508fb5ef5aSBrian Somers u_char b[16]; 1518fb5ef5aSBrian Somers const u_char *A, *C; 1528fb5ef5aSBrian Somers MD5_CTX Context; 1538fb5ef5aSBrian Somers int Slen, i, Clen, Ppos; 1548fb5ef5aSBrian Somers u_char *P; 1558fb5ef5aSBrian Somers 1568fb5ef5aSBrian Somers if (mlen % 16 != SALT_LEN) { 1578fb5ef5aSBrian Somers log_Printf(LogWARN, "Cannot interpret mangled data of length %ld\n", 1588fb5ef5aSBrian Somers (u_long)mlen); 1598fb5ef5aSBrian Somers *buf = NULL; 1608fb5ef5aSBrian Somers *len = 0; 1618fb5ef5aSBrian Somers return; 1628fb5ef5aSBrian Somers } 1638fb5ef5aSBrian Somers 1648fb5ef5aSBrian Somers /* We need the RADIUS Request-Authenticator */ 1658fb5ef5aSBrian Somers if (rad_request_authenticator(r->cx.rad, R, sizeof R) != AUTH_LEN) { 1668fb5ef5aSBrian Somers log_Printf(LogWARN, "Cannot obtain the RADIUS request authenticator\n"); 1678fb5ef5aSBrian Somers *buf = NULL; 1688fb5ef5aSBrian Somers *len = 0; 1698fb5ef5aSBrian Somers return; 1708fb5ef5aSBrian Somers } 1718fb5ef5aSBrian Somers 1728fb5ef5aSBrian Somers A = (const u_char *)mangled; /* Salt comes first */ 1738fb5ef5aSBrian Somers C = (const u_char *)mangled + SALT_LEN; /* Then the ciphertext */ 1748fb5ef5aSBrian Somers Clen = mlen - SALT_LEN; 1758fb5ef5aSBrian Somers S = rad_server_secret(r->cx.rad); /* We need the RADIUS secret */ 1768fb5ef5aSBrian Somers Slen = strlen(S); 1778fb5ef5aSBrian Somers P = alloca(Clen); /* We derive our plaintext */ 1788fb5ef5aSBrian Somers 1798fb5ef5aSBrian Somers MD5Init(&Context); 1808fb5ef5aSBrian Somers MD5Update(&Context, S, Slen); 1818fb5ef5aSBrian Somers MD5Update(&Context, R, AUTH_LEN); 1828fb5ef5aSBrian Somers MD5Update(&Context, A, SALT_LEN); 1838fb5ef5aSBrian Somers MD5Final(b, &Context); 1848fb5ef5aSBrian Somers Ppos = 0; 1858fb5ef5aSBrian Somers 1868fb5ef5aSBrian Somers while (Clen) { 1878fb5ef5aSBrian Somers Clen -= 16; 1888fb5ef5aSBrian Somers 1898fb5ef5aSBrian Somers for (i = 0; i < 16; i++) 1908fb5ef5aSBrian Somers P[Ppos++] = C[i] ^ b[i]; 1918fb5ef5aSBrian Somers 1928fb5ef5aSBrian Somers if (Clen) { 1938fb5ef5aSBrian Somers MD5Init(&Context); 1948fb5ef5aSBrian Somers MD5Update(&Context, S, Slen); 1958fb5ef5aSBrian Somers MD5Update(&Context, C, 16); 1968fb5ef5aSBrian Somers MD5Final(b, &Context); 1978fb5ef5aSBrian Somers } 1988fb5ef5aSBrian Somers 1998fb5ef5aSBrian Somers C += 16; 2008fb5ef5aSBrian Somers } 2018fb5ef5aSBrian Somers 2028fb5ef5aSBrian Somers /* 2038fb5ef5aSBrian Somers * The resulting plain text consists of a one-byte length, the text and 2048fb5ef5aSBrian Somers * maybe some padding. 2058fb5ef5aSBrian Somers */ 2068fb5ef5aSBrian Somers *len = *P; 2078fb5ef5aSBrian Somers if (*len > mlen - 1) { 2088fb5ef5aSBrian Somers log_Printf(LogWARN, "Mangled data seems to be garbage\n"); 2098fb5ef5aSBrian Somers *buf = NULL; 2108fb5ef5aSBrian Somers *len = 0; 2118fb5ef5aSBrian Somers return; 2128fb5ef5aSBrian Somers } 2138fb5ef5aSBrian Somers 2148fb5ef5aSBrian Somers *buf = malloc(*len); 2158fb5ef5aSBrian Somers memcpy(*buf, P + 1, *len); 2168fb5ef5aSBrian Somers } 217ff8e577bSBrian Somers #endif 218972a1bcfSBrian Somers 219ec3e98b8SHajimu UMEMOTO /* XXX: This should go into librarius. */ 220ec3e98b8SHajimu UMEMOTO #ifndef NOINET6 221ec3e98b8SHajimu UMEMOTO static uint8_t * 222ec3e98b8SHajimu UMEMOTO rad_cvt_ipv6prefix(const void *data, size_t len) 223ec3e98b8SHajimu UMEMOTO { 224ec3e98b8SHajimu UMEMOTO const size_t ipv6len = sizeof(struct in6_addr) + 2; 225ec3e98b8SHajimu UMEMOTO uint8_t *s; 226ec3e98b8SHajimu UMEMOTO 227ec3e98b8SHajimu UMEMOTO if (len > ipv6len) 228ec3e98b8SHajimu UMEMOTO return NULL; 229ec3e98b8SHajimu UMEMOTO s = malloc(ipv6len); 230ec3e98b8SHajimu UMEMOTO if (s != NULL) { 231ec3e98b8SHajimu UMEMOTO memset(s, 0, ipv6len); 232ec3e98b8SHajimu UMEMOTO memcpy(s, data, len); 233ec3e98b8SHajimu UMEMOTO } 234ec3e98b8SHajimu UMEMOTO return s; 235ec3e98b8SHajimu UMEMOTO } 236ec3e98b8SHajimu UMEMOTO #endif 237ec3e98b8SHajimu UMEMOTO 238f0cdd9c0SBrian Somers /* 239f0cdd9c0SBrian Somers * rad_continue_send_request() has given us `got' (non-zero). Deal with it. 240f0cdd9c0SBrian Somers */ 241f0cdd9c0SBrian Somers static void 242f0cdd9c0SBrian Somers radius_Process(struct radius *r, int got) 243972a1bcfSBrian Somers { 244972a1bcfSBrian Somers char *argv[MAXARGS], *nuke; 245f0cdd9c0SBrian Somers struct bundle *bundle; 246ff8e577bSBrian Somers int argc, addrs, res, width; 24728e610e3SBrian Somers size_t len; 24830949fd4SBrian Somers struct ncprange dest; 24930949fd4SBrian Somers struct ncpaddr gw; 250f0cdd9c0SBrian Somers const void *data; 251c42627ffSBrian Somers const char *stype; 252ff8e577bSBrian Somers u_int32_t ipaddr, vendor; 25330949fd4SBrian Somers struct in_addr ip; 2540fe74aa4SHajimu UMEMOTO #ifndef NOINET6 255ec3e98b8SHajimu UMEMOTO uint8_t ipv6addr[INET6_ADDRSTRLEN]; 2560fe74aa4SHajimu UMEMOTO struct in6_addr ip6; 2570fe74aa4SHajimu UMEMOTO #endif 258972a1bcfSBrian Somers 259f0cdd9c0SBrian Somers r->cx.fd = -1; /* Stop select()ing */ 260c42627ffSBrian Somers stype = r->cx.auth ? "auth" : "acct"; 261972a1bcfSBrian Somers 262972a1bcfSBrian Somers switch (got) { 263972a1bcfSBrian Somers case RAD_ACCESS_ACCEPT: 264c42627ffSBrian Somers log_Printf(LogPHASE, "Radius(%s): ACCEPT received\n", stype); 265c42627ffSBrian Somers if (!r->cx.auth) { 266c42627ffSBrian Somers rad_close(r->cx.rad); 267c42627ffSBrian Somers return; 268c42627ffSBrian Somers } 269972a1bcfSBrian Somers break; 270972a1bcfSBrian Somers 271f0cdd9c0SBrian Somers case RAD_ACCESS_REJECT: 272c42627ffSBrian Somers log_Printf(LogPHASE, "Radius(%s): REJECT received\n", stype); 273ff8e577bSBrian Somers if (!r->cx.auth) { 274f0cdd9c0SBrian Somers rad_close(r->cx.rad); 275f0cdd9c0SBrian Somers return; 276ff8e577bSBrian Somers } 277ff8e577bSBrian Somers break; 278f0cdd9c0SBrian Somers 279972a1bcfSBrian Somers case RAD_ACCESS_CHALLENGE: 280972a1bcfSBrian Somers /* we can't deal with this (for now) ! */ 281f0cdd9c0SBrian Somers log_Printf(LogPHASE, "Radius: CHALLENGE received (can't handle yet)\n"); 282c42627ffSBrian Somers if (r->cx.auth) 283f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 284f0cdd9c0SBrian Somers rad_close(r->cx.rad); 285f0cdd9c0SBrian Somers return; 286972a1bcfSBrian Somers 287794c9bbcSBrian Somers case RAD_ACCOUNTING_RESPONSE: 288c42627ffSBrian Somers log_Printf(LogPHASE, "Radius(%s): Accounting response received\n", stype); 289c42627ffSBrian Somers if (r->cx.auth) 290c42627ffSBrian Somers auth_Failure(r->cx.auth); /* unexpected !!! */ 291c42627ffSBrian Somers 292794c9bbcSBrian Somers /* No further processing for accounting requests, please */ 293794c9bbcSBrian Somers rad_close(r->cx.rad); 294794c9bbcSBrian Somers return; 295794c9bbcSBrian Somers 296972a1bcfSBrian Somers case -1: 297c42627ffSBrian Somers log_Printf(LogPHASE, "radius(%s): %s\n", stype, rad_strerror(r->cx.rad)); 298c42627ffSBrian Somers if (r->cx.auth) 299f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 300f0cdd9c0SBrian Somers rad_close(r->cx.rad); 301f0cdd9c0SBrian Somers return; 302972a1bcfSBrian Somers 303972a1bcfSBrian Somers default: 304c42627ffSBrian Somers log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype, 305f0cdd9c0SBrian Somers got, rad_strerror(r->cx.rad)); 306c42627ffSBrian Somers if (r->cx.auth) 307f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 308f0cdd9c0SBrian Somers rad_close(r->cx.rad); 309f0cdd9c0SBrian Somers return; 310972a1bcfSBrian Somers } 311972a1bcfSBrian Somers 312ff8e577bSBrian Somers /* Let's see what we've got in our reply */ 313972a1bcfSBrian Somers r->ip.s_addr = r->mask.s_addr = INADDR_NONE; 314972a1bcfSBrian Somers r->mtu = 0; 315972a1bcfSBrian Somers r->vj = 0; 316ff8e577bSBrian Somers while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) { 317ff8e577bSBrian Somers switch (res) { 318972a1bcfSBrian Somers case RAD_FRAMED_IP_ADDRESS: 319972a1bcfSBrian Somers r->ip = rad_cvt_addr(data); 320f0cdd9c0SBrian Somers log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip)); 321972a1bcfSBrian Somers break; 322972a1bcfSBrian Somers 323bf1eaec5SBrian Somers case RAD_FILTER_ID: 324bf1eaec5SBrian Somers free(r->filterid); 325bf1eaec5SBrian Somers if ((r->filterid = rad_cvt_string(data, len)) == NULL) { 326bf1eaec5SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 327ff8e577bSBrian Somers auth_Failure(r->cx.auth); 328bf1eaec5SBrian Somers rad_close(r->cx.rad); 329bf1eaec5SBrian Somers return; 330bf1eaec5SBrian Somers } 331bf1eaec5SBrian Somers log_Printf(LogPHASE, " Filter \"%s\"\n", r->filterid); 332bf1eaec5SBrian Somers break; 333bf1eaec5SBrian Somers 334bf1eaec5SBrian Somers case RAD_SESSION_TIMEOUT: 335bf1eaec5SBrian Somers r->sessiontime = rad_cvt_int(data); 336bf1eaec5SBrian Somers log_Printf(LogPHASE, " Session-Timeout %lu\n", r->sessiontime); 337bf1eaec5SBrian Somers break; 338bf1eaec5SBrian Somers 339972a1bcfSBrian Somers case RAD_FRAMED_IP_NETMASK: 340972a1bcfSBrian Somers r->mask = rad_cvt_addr(data); 341f0cdd9c0SBrian Somers log_Printf(LogPHASE, " Netmask %s\n", inet_ntoa(r->mask)); 342972a1bcfSBrian Somers break; 343972a1bcfSBrian Somers 344972a1bcfSBrian Somers case RAD_FRAMED_MTU: 345972a1bcfSBrian Somers r->mtu = rad_cvt_int(data); 346f0cdd9c0SBrian Somers log_Printf(LogPHASE, " MTU %lu\n", r->mtu); 347972a1bcfSBrian Somers break; 348972a1bcfSBrian Somers 349972a1bcfSBrian Somers case RAD_FRAMED_ROUTING: 350972a1bcfSBrian Somers /* Disabled for now - should we automatically set up some filters ? */ 351972a1bcfSBrian Somers /* rad_cvt_int(data); */ 352972a1bcfSBrian Somers /* bit 1 = Send routing packets */ 353972a1bcfSBrian Somers /* bit 2 = Receive routing packets */ 354972a1bcfSBrian Somers break; 355972a1bcfSBrian Somers 356972a1bcfSBrian Somers case RAD_FRAMED_COMPRESSION: 357972a1bcfSBrian Somers r->vj = rad_cvt_int(data) == 1 ? 1 : 0; 358f0cdd9c0SBrian Somers log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis"); 359972a1bcfSBrian Somers break; 360972a1bcfSBrian Somers 361972a1bcfSBrian Somers case RAD_FRAMED_ROUTE: 362972a1bcfSBrian Somers /* 363972a1bcfSBrian Somers * We expect a string of the format ``dest[/bits] gw [metrics]'' 364972a1bcfSBrian Somers * Any specified metrics are ignored. MYADDR and HISADDR are 365972a1bcfSBrian Somers * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same 366972a1bcfSBrian Somers * as ``HISADDR''. 367972a1bcfSBrian Somers */ 368972a1bcfSBrian Somers 369972a1bcfSBrian Somers if ((nuke = rad_cvt_string(data, len)) == NULL) { 370f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 371ff8e577bSBrian Somers auth_Failure(r->cx.auth); 372f0cdd9c0SBrian Somers rad_close(r->cx.rad); 373f0cdd9c0SBrian Somers return; 374972a1bcfSBrian Somers } 375972a1bcfSBrian Somers 376f0cdd9c0SBrian Somers log_Printf(LogPHASE, " Route: %s\n", nuke); 377f0cdd9c0SBrian Somers bundle = r->cx.auth->physical->dl->bundle; 37830949fd4SBrian Somers ip.s_addr = INADDR_ANY; 3790fe74aa4SHajimu UMEMOTO ncpaddr_setip4(&gw, ip); 38030949fd4SBrian Somers ncprange_setip4host(&dest, ip); 381972a1bcfSBrian Somers argc = command_Interpret(nuke, strlen(nuke), argv); 382c39aa54eSBrian Somers if (argc < 0) 383c39aa54eSBrian Somers log_Printf(LogWARN, "radius: %s: Syntax error\n", 384c39aa54eSBrian Somers argc == 1 ? argv[0] : "\"\""); 385c39aa54eSBrian Somers else if (argc < 2) 386972a1bcfSBrian Somers log_Printf(LogWARN, "radius: %s: Invalid route\n", 387972a1bcfSBrian Somers argc == 1 ? argv[0] : "\"\""); 388972a1bcfSBrian Somers else if ((strcasecmp(argv[0], "default") != 0 && 38930949fd4SBrian Somers !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 39030949fd4SBrian Somers !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 391972a1bcfSBrian Somers log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 392972a1bcfSBrian Somers argv[0], argv[1]); 393972a1bcfSBrian Somers else { 39430949fd4SBrian Somers ncprange_getwidth(&dest, &width); 39530949fd4SBrian Somers if (width == 32 && strchr(argv[0], '/') == NULL) { 396972a1bcfSBrian Somers /* No mask specified - use the natural mask */ 39730949fd4SBrian Somers ncprange_getip4addr(&dest, &ip); 39830949fd4SBrian Somers ncprange_setip4mask(&dest, addr2mask(ip)); 39930949fd4SBrian Somers } 400972a1bcfSBrian Somers addrs = 0; 401972a1bcfSBrian Somers 402972a1bcfSBrian Somers if (!strncasecmp(argv[0], "HISADDR", 7)) 403972a1bcfSBrian Somers addrs = ROUTE_DSTHISADDR; 404972a1bcfSBrian Somers else if (!strncasecmp(argv[0], "MYADDR", 6)) 405972a1bcfSBrian Somers addrs = ROUTE_DSTMYADDR; 406972a1bcfSBrian Somers 40730949fd4SBrian Somers if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) { 408972a1bcfSBrian Somers addrs |= ROUTE_GWHISADDR; 40930949fd4SBrian Somers ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip); 410972a1bcfSBrian Somers } else if (strcasecmp(argv[1], "HISADDR") == 0) 411972a1bcfSBrian Somers addrs |= ROUTE_GWHISADDR; 412972a1bcfSBrian Somers 41330949fd4SBrian Somers route_Add(&r->routes, addrs, &dest, &gw); 414972a1bcfSBrian Somers } 415972a1bcfSBrian Somers free(nuke); 416972a1bcfSBrian Somers break; 417972a1bcfSBrian Somers 418ff8e577bSBrian Somers case RAD_REPLY_MESSAGE: 419ff8e577bSBrian Somers free(r->repstr); 420ff8e577bSBrian Somers if ((r->repstr = rad_cvt_string(data, len)) == NULL) { 421ff8e577bSBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 422ff8e577bSBrian Somers auth_Failure(r->cx.auth); 423ff8e577bSBrian Somers rad_close(r->cx.rad); 424ff8e577bSBrian Somers return; 425ff8e577bSBrian Somers } 426ff8e577bSBrian Somers log_Printf(LogPHASE, " Reply-Message \"%s\"\n", r->repstr); 427ff8e577bSBrian Somers break; 428ff8e577bSBrian Somers 4290fe74aa4SHajimu UMEMOTO #ifndef NOINET6 430ec3e98b8SHajimu UMEMOTO case RAD_FRAMED_IPV6_PREFIX: 431ec3e98b8SHajimu UMEMOTO free(r->ipv6prefix); 432ec3e98b8SHajimu UMEMOTO r->ipv6prefix = rad_cvt_ipv6prefix(data, len); 433ec3e98b8SHajimu UMEMOTO inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr)); 434ec3e98b8SHajimu UMEMOTO log_Printf(LogPHASE, " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]); 435ec3e98b8SHajimu UMEMOTO break; 436ec3e98b8SHajimu UMEMOTO 4370fe74aa4SHajimu UMEMOTO case RAD_FRAMED_IPV6_ROUTE: 4380fe74aa4SHajimu UMEMOTO /* 4390fe74aa4SHajimu UMEMOTO * We expect a string of the format ``dest[/bits] gw [metrics]'' 4400fe74aa4SHajimu UMEMOTO * Any specified metrics are ignored. MYADDR6 and HISADDR6 are 4410fe74aa4SHajimu UMEMOTO * understood for ``dest'' and ``gw'' and ``::'' is the same 4420fe74aa4SHajimu UMEMOTO * as ``HISADDR6''. 4430fe74aa4SHajimu UMEMOTO */ 4440fe74aa4SHajimu UMEMOTO 4450fe74aa4SHajimu UMEMOTO if ((nuke = rad_cvt_string(data, len)) == NULL) { 4460fe74aa4SHajimu UMEMOTO log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 4470fe74aa4SHajimu UMEMOTO auth_Failure(r->cx.auth); 4480fe74aa4SHajimu UMEMOTO rad_close(r->cx.rad); 4490fe74aa4SHajimu UMEMOTO return; 4500fe74aa4SHajimu UMEMOTO } 4510fe74aa4SHajimu UMEMOTO 4520fe74aa4SHajimu UMEMOTO log_Printf(LogPHASE, " IPv6 Route: %s\n", nuke); 4530fe74aa4SHajimu UMEMOTO bundle = r->cx.auth->physical->dl->bundle; 4540fe74aa4SHajimu UMEMOTO ncpaddr_setip6(&gw, &in6addr_any); 4550fe74aa4SHajimu UMEMOTO ncprange_set(&dest, &gw, 0); 4560fe74aa4SHajimu UMEMOTO argc = command_Interpret(nuke, strlen(nuke), argv); 4570fe74aa4SHajimu UMEMOTO if (argc < 0) 4580fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s: Syntax error\n", 4590fe74aa4SHajimu UMEMOTO argc == 1 ? argv[0] : "\"\""); 4600fe74aa4SHajimu UMEMOTO else if (argc < 2) 4610fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s: Invalid route\n", 4620fe74aa4SHajimu UMEMOTO argc == 1 ? argv[0] : "\"\""); 4630fe74aa4SHajimu UMEMOTO else if ((strcasecmp(argv[0], "default") != 0 && 4640fe74aa4SHajimu UMEMOTO !ncprange_aton(&dest, &bundle->ncp, argv[0])) || 4650fe74aa4SHajimu UMEMOTO !ncpaddr_aton(&gw, &bundle->ncp, argv[1])) 4660fe74aa4SHajimu UMEMOTO log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 4670fe74aa4SHajimu UMEMOTO argv[0], argv[1]); 4680fe74aa4SHajimu UMEMOTO else { 4690fe74aa4SHajimu UMEMOTO addrs = 0; 4700fe74aa4SHajimu UMEMOTO 4710fe74aa4SHajimu UMEMOTO if (!strncasecmp(argv[0], "HISADDR6", 8)) 4720fe74aa4SHajimu UMEMOTO addrs = ROUTE_DSTHISADDR6; 4730fe74aa4SHajimu UMEMOTO else if (!strncasecmp(argv[0], "MYADDR6", 7)) 4740fe74aa4SHajimu UMEMOTO addrs = ROUTE_DSTMYADDR6; 4750fe74aa4SHajimu UMEMOTO 4760fe74aa4SHajimu UMEMOTO if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) { 4770fe74aa4SHajimu UMEMOTO addrs |= ROUTE_GWHISADDR6; 4780fe74aa4SHajimu UMEMOTO ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr); 4790fe74aa4SHajimu UMEMOTO } else if (strcasecmp(argv[1], "HISADDR6") == 0) 4800fe74aa4SHajimu UMEMOTO addrs |= ROUTE_GWHISADDR6; 4810fe74aa4SHajimu UMEMOTO 4820fe74aa4SHajimu UMEMOTO route_Add(&r->ipv6routes, addrs, &dest, &gw); 4830fe74aa4SHajimu UMEMOTO } 4840fe74aa4SHajimu UMEMOTO free(nuke); 4850fe74aa4SHajimu UMEMOTO break; 4860fe74aa4SHajimu UMEMOTO #endif 4870fe74aa4SHajimu UMEMOTO 488ff8e577bSBrian Somers case RAD_VENDOR_SPECIFIC: 489ff8e577bSBrian Somers if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) { 490ff8e577bSBrian Somers log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n", 491f0cdd9c0SBrian Somers rad_strerror(r->cx.rad)); 492f0cdd9c0SBrian Somers auth_Failure(r->cx.auth); 493f0cdd9c0SBrian Somers rad_close(r->cx.rad); 494ff8e577bSBrian Somers return; 495ff8e577bSBrian Somers } 496ff8e577bSBrian Somers 497ff8e577bSBrian Somers switch (vendor) { 498ff8e577bSBrian Somers case RAD_VENDOR_MICROSOFT: 499ff8e577bSBrian Somers switch (res) { 5008fb5ef5aSBrian Somers #ifndef NODES 501ff8e577bSBrian Somers case RAD_MICROSOFT_MS_CHAP_ERROR: 502ff8e577bSBrian Somers free(r->errstr); 503a95b23a6SBrian Somers if (len == 0) 504a95b23a6SBrian Somers r->errstr = NULL; 505a95b23a6SBrian Somers else { 50699cfc2e2SBrian Somers if (len < 3 || ((const char *)data)[1] != '=') { 50799cfc2e2SBrian Somers /* 50899cfc2e2SBrian Somers * Only point at the String field if we don't think the 50999cfc2e2SBrian Somers * peer has misformatted the response. 51099cfc2e2SBrian Somers */ 51199cfc2e2SBrian Somers ((const char *)data)++; 51299cfc2e2SBrian Somers len--; 513579abfd8SBrian Somers } else 514579abfd8SBrian Somers log_Printf(LogWARN, "Warning: The MS-CHAP-Error " 515579abfd8SBrian Somers "attribute is mis-formatted. Compensating\n"); 51699cfc2e2SBrian Somers if ((r->errstr = rad_cvt_string((const char *)data, 51799cfc2e2SBrian Somers len)) == NULL) { 518ff8e577bSBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", 519ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 520ff8e577bSBrian Somers auth_Failure(r->cx.auth); 521ff8e577bSBrian Somers rad_close(r->cx.rad); 522ff8e577bSBrian Somers return; 523ff8e577bSBrian Somers } 524ff8e577bSBrian Somers log_Printf(LogPHASE, " MS-CHAP-Error \"%s\"\n", r->errstr); 525a95b23a6SBrian Somers } 526ff8e577bSBrian Somers break; 527ff8e577bSBrian Somers 528a16061b2SBrian Somers case RAD_MICROSOFT_MS_CHAP2_SUCCESS: 529a16061b2SBrian Somers free(r->msrepstr); 530a95b23a6SBrian Somers if (len == 0) 531a95b23a6SBrian Somers r->msrepstr = NULL; 532a95b23a6SBrian Somers else { 53399cfc2e2SBrian Somers if (len < 3 || ((const char *)data)[1] != '=') { 53499cfc2e2SBrian Somers /* 53599cfc2e2SBrian Somers * Only point at the String field if we don't think the 53699cfc2e2SBrian Somers * peer has misformatted the response. 53799cfc2e2SBrian Somers */ 53899cfc2e2SBrian Somers ((const char *)data)++; 53999cfc2e2SBrian Somers len--; 540579abfd8SBrian Somers } else 541579abfd8SBrian Somers log_Printf(LogWARN, "Warning: The MS-CHAP2-Success " 542579abfd8SBrian Somers "attribute is mis-formatted. Compensating\n"); 54399cfc2e2SBrian Somers if ((r->msrepstr = rad_cvt_string((const char *)data, 54499cfc2e2SBrian Somers len)) == NULL) { 545a16061b2SBrian Somers log_Printf(LogERROR, "rad_cvt_string: %s\n", 546a16061b2SBrian Somers rad_strerror(r->cx.rad)); 547a16061b2SBrian Somers auth_Failure(r->cx.auth); 548a16061b2SBrian Somers rad_close(r->cx.rad); 549a16061b2SBrian Somers return; 550a16061b2SBrian Somers } 551a95b23a6SBrian Somers log_Printf(LogPHASE, " MS-CHAP2-Success \"%s\"\n", 552a95b23a6SBrian Somers r->msrepstr); 553a95b23a6SBrian Somers } 554a16061b2SBrian Somers break; 555a16061b2SBrian Somers 5568fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY: 5578fb5ef5aSBrian Somers r->mppe.policy = rad_cvt_int(data); 5588fb5ef5aSBrian Somers log_Printf(LogPHASE, " MS-MPPE-Encryption-Policy %s\n", 5598fb5ef5aSBrian Somers radius_policyname(r->mppe.policy)); 5608fb5ef5aSBrian Somers break; 5618fb5ef5aSBrian Somers 5628fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES: 5638fb5ef5aSBrian Somers r->mppe.types = rad_cvt_int(data); 5648fb5ef5aSBrian Somers log_Printf(LogPHASE, " MS-MPPE-Encryption-Types %s\n", 5658fb5ef5aSBrian Somers radius_typesname(r->mppe.types)); 5668fb5ef5aSBrian Somers break; 5678fb5ef5aSBrian Somers 5688fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_RECV_KEY: 5698fb5ef5aSBrian Somers free(r->mppe.recvkey); 5708fb5ef5aSBrian Somers demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen); 5718fb5ef5aSBrian Somers log_Printf(LogPHASE, " MS-MPPE-Recv-Key ********\n"); 5728fb5ef5aSBrian Somers break; 5738fb5ef5aSBrian Somers 5748fb5ef5aSBrian Somers case RAD_MICROSOFT_MS_MPPE_SEND_KEY: 5758fb5ef5aSBrian Somers demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen); 5768fb5ef5aSBrian Somers log_Printf(LogPHASE, " MS-MPPE-Send-Key ********\n"); 5778fb5ef5aSBrian Somers break; 5788fb5ef5aSBrian Somers #endif 5798fb5ef5aSBrian Somers 580ff8e577bSBrian Somers default: 581ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific " 582ff8e577bSBrian Somers "RADIUS attribute %d\n", res); 583ff8e577bSBrian Somers break; 584ff8e577bSBrian Somers } 585ff8e577bSBrian Somers break; 586ff8e577bSBrian Somers 587ff8e577bSBrian Somers default: 588ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n", 589ff8e577bSBrian Somers (unsigned long)vendor, res); 590ff8e577bSBrian Somers break; 591ff8e577bSBrian Somers } 592ff8e577bSBrian Somers break; 593ff8e577bSBrian Somers 594ff8e577bSBrian Somers default: 595ff8e577bSBrian Somers log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res); 596ff8e577bSBrian Somers break; 597ff8e577bSBrian Somers } 598ff8e577bSBrian Somers } 599ff8e577bSBrian Somers 600ff8e577bSBrian Somers if (res == -1) { 601ff8e577bSBrian Somers log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n", 602ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 603ff8e577bSBrian Somers auth_Failure(r->cx.auth); 604ff8e577bSBrian Somers } else if (got == RAD_ACCESS_REJECT) 605ff8e577bSBrian Somers auth_Failure(r->cx.auth); 606ff8e577bSBrian Somers else { 607f0cdd9c0SBrian Somers r->valid = 1; 608f0cdd9c0SBrian Somers auth_Success(r->cx.auth); 609f0cdd9c0SBrian Somers } 610ff8e577bSBrian Somers rad_close(r->cx.rad); 611972a1bcfSBrian Somers } 612972a1bcfSBrian Somers 613f0cdd9c0SBrian Somers /* 6148e7bd08eSBrian Somers * We've either timed out or select()ed on the read descriptor 615f0cdd9c0SBrian Somers */ 616f0cdd9c0SBrian Somers static void 617f0cdd9c0SBrian Somers radius_Continue(struct radius *r, int sel) 618f0cdd9c0SBrian Somers { 619f0cdd9c0SBrian Somers struct timeval tv; 620f0cdd9c0SBrian Somers int got; 621972a1bcfSBrian Somers 622f0cdd9c0SBrian Somers timer_Stop(&r->cx.timer); 623f0cdd9c0SBrian Somers if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) { 624f0cdd9c0SBrian Somers log_Printf(LogPHASE, "Radius: Request re-sent\n"); 625f0cdd9c0SBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 626f0cdd9c0SBrian Somers timer_Start(&r->cx.timer); 627f0cdd9c0SBrian Somers return; 628f0cdd9c0SBrian Somers } 629f0cdd9c0SBrian Somers 630f0cdd9c0SBrian Somers radius_Process(r, got); 631f0cdd9c0SBrian Somers } 632f0cdd9c0SBrian Somers 633f0cdd9c0SBrian Somers /* 634f0cdd9c0SBrian Somers * Time to call rad_continue_send_request() - timed out. 635f0cdd9c0SBrian Somers */ 636f0cdd9c0SBrian Somers static void 637f0cdd9c0SBrian Somers radius_Timeout(void *v) 638f0cdd9c0SBrian Somers { 639f0cdd9c0SBrian Somers radius_Continue((struct radius *)v, 0); 640f0cdd9c0SBrian Somers } 641f0cdd9c0SBrian Somers 642f0cdd9c0SBrian Somers /* 643f0cdd9c0SBrian Somers * Time to call rad_continue_send_request() - something to read. 644f0cdd9c0SBrian Somers */ 645f0cdd9c0SBrian Somers static void 646f013f33eSBrian Somers radius_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 647f0cdd9c0SBrian Somers { 648f0cdd9c0SBrian Somers radius_Continue(descriptor2radius(d), 1); 649f0cdd9c0SBrian Somers } 650f0cdd9c0SBrian Somers 651f0cdd9c0SBrian Somers /* 6528e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 653f0cdd9c0SBrian Somers */ 654f0cdd9c0SBrian Somers static int 655f013f33eSBrian Somers radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 656f0cdd9c0SBrian Somers { 657f0cdd9c0SBrian Somers struct radius *rad = descriptor2radius(d); 658f0cdd9c0SBrian Somers 659f0cdd9c0SBrian Somers if (r && rad->cx.fd != -1) { 660f0cdd9c0SBrian Somers FD_SET(rad->cx.fd, r); 661f0cdd9c0SBrian Somers if (*n < rad->cx.fd + 1) 662f0cdd9c0SBrian Somers *n = rad->cx.fd + 1; 663f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd); 66482d6780cSBrian Somers return 1; 665972a1bcfSBrian Somers } 666972a1bcfSBrian Somers 667f0cdd9c0SBrian Somers return 0; 668f0cdd9c0SBrian Somers } 669f0cdd9c0SBrian Somers 670f0cdd9c0SBrian Somers /* 6718e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 672f0cdd9c0SBrian Somers */ 673f0cdd9c0SBrian Somers static int 674f013f33eSBrian Somers radius_IsSet(struct fdescriptor *d, const fd_set *fdset) 675f0cdd9c0SBrian Somers { 676f0cdd9c0SBrian Somers struct radius *r = descriptor2radius(d); 677f0cdd9c0SBrian Somers 678f0cdd9c0SBrian Somers return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset); 679f0cdd9c0SBrian Somers } 680f0cdd9c0SBrian Somers 681f0cdd9c0SBrian Somers /* 6828e7bd08eSBrian Somers * Behave as a struct fdescriptor (descriptor.h) 683f0cdd9c0SBrian Somers */ 684f0cdd9c0SBrian Somers static int 685f013f33eSBrian Somers radius_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 686f0cdd9c0SBrian Somers { 687f0cdd9c0SBrian Somers /* We never want to write here ! */ 688f0cdd9c0SBrian Somers log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n"); 689f0cdd9c0SBrian Somers return 0; 690f0cdd9c0SBrian Somers } 691f0cdd9c0SBrian Somers 692f0cdd9c0SBrian Somers /* 693f0cdd9c0SBrian Somers * Initialise ourselves 694f0cdd9c0SBrian Somers */ 695f0cdd9c0SBrian Somers void 696f0cdd9c0SBrian Somers radius_Init(struct radius *r) 697f0cdd9c0SBrian Somers { 698f0cdd9c0SBrian Somers r->desc.type = RADIUS_DESCRIPTOR; 699f0cdd9c0SBrian Somers r->desc.UpdateSet = radius_UpdateSet; 700f0cdd9c0SBrian Somers r->desc.IsSet = radius_IsSet; 701f0cdd9c0SBrian Somers r->desc.Read = radius_Read; 702f0cdd9c0SBrian Somers r->desc.Write = radius_Write; 703ff8e577bSBrian Somers r->cx.fd = -1; 704ff8e577bSBrian Somers r->cx.rad = NULL; 705f0cdd9c0SBrian Somers memset(&r->cx.timer, '\0', sizeof r->cx.timer); 706ff8e577bSBrian Somers r->cx.auth = NULL; 707ff8e577bSBrian Somers r->valid = 0; 708ff8e577bSBrian Somers r->vj = 0; 709ff8e577bSBrian Somers r->ip.s_addr = INADDR_ANY; 710ff8e577bSBrian Somers r->mask.s_addr = INADDR_NONE; 711ff8e577bSBrian Somers r->routes = NULL; 712ff8e577bSBrian Somers r->mtu = DEF_MTU; 713a16061b2SBrian Somers r->msrepstr = NULL; 714ff8e577bSBrian Somers r->repstr = NULL; 7150fe74aa4SHajimu UMEMOTO #ifndef NOINET6 716ec3e98b8SHajimu UMEMOTO r->ipv6prefix = NULL; 7170fe74aa4SHajimu UMEMOTO r->ipv6routes = NULL; 7180fe74aa4SHajimu UMEMOTO #endif 719ff8e577bSBrian Somers r->errstr = NULL; 7208fb5ef5aSBrian Somers r->mppe.policy = 0; 7218fb5ef5aSBrian Somers r->mppe.types = 0; 7228fb5ef5aSBrian Somers r->mppe.recvkey = NULL; 7238fb5ef5aSBrian Somers r->mppe.recvkeylen = 0; 7248fb5ef5aSBrian Somers r->mppe.sendkey = NULL; 7258fb5ef5aSBrian Somers r->mppe.sendkeylen = 0; 726ff8e577bSBrian Somers *r->cfg.file = '\0';; 727794c9bbcSBrian Somers log_Printf(LogDEBUG, "Radius: radius_Init\n"); 728f0cdd9c0SBrian Somers } 729f0cdd9c0SBrian Somers 730f0cdd9c0SBrian Somers /* 731f0cdd9c0SBrian Somers * Forget everything and go back to initialised state. 732f0cdd9c0SBrian Somers */ 733f0cdd9c0SBrian Somers void 734f0cdd9c0SBrian Somers radius_Destroy(struct radius *r) 735f0cdd9c0SBrian Somers { 736f0cdd9c0SBrian Somers r->valid = 0; 737794c9bbcSBrian Somers log_Printf(LogDEBUG, "Radius: radius_Destroy\n"); 738f0cdd9c0SBrian Somers timer_Stop(&r->cx.timer); 739f0cdd9c0SBrian Somers route_DeleteAll(&r->routes); 7400fe74aa4SHajimu UMEMOTO #ifndef NOINET6 7410fe74aa4SHajimu UMEMOTO route_DeleteAll(&r->ipv6routes); 7420fe74aa4SHajimu UMEMOTO #endif 743bf1eaec5SBrian Somers free(r->filterid); 744bf1eaec5SBrian Somers r->filterid = NULL; 745a16061b2SBrian Somers free(r->msrepstr); 746a16061b2SBrian Somers r->msrepstr = NULL; 747ff8e577bSBrian Somers free(r->repstr); 748ff8e577bSBrian Somers r->repstr = NULL; 749ec3e98b8SHajimu UMEMOTO #ifndef NOINET6 750ec3e98b8SHajimu UMEMOTO free(r->ipv6prefix); 751ec3e98b8SHajimu UMEMOTO r->ipv6prefix = NULL; 752ec3e98b8SHajimu UMEMOTO #endif 753ff8e577bSBrian Somers free(r->errstr); 754ff8e577bSBrian Somers r->errstr = NULL; 7558fb5ef5aSBrian Somers free(r->mppe.recvkey); 7568fb5ef5aSBrian Somers r->mppe.recvkey = NULL; 7578fb5ef5aSBrian Somers r->mppe.recvkeylen = 0; 7588fb5ef5aSBrian Somers free(r->mppe.sendkey); 7598fb5ef5aSBrian Somers r->mppe.sendkey = NULL; 7608fb5ef5aSBrian Somers r->mppe.sendkeylen = 0; 761f0cdd9c0SBrian Somers if (r->cx.fd != -1) { 762f0cdd9c0SBrian Somers r->cx.fd = -1; 763f0cdd9c0SBrian Somers rad_close(r->cx.rad); 764f0cdd9c0SBrian Somers } 765f0cdd9c0SBrian Somers } 766f0cdd9c0SBrian Somers 767de59e178SBrian Somers static int 768de59e178SBrian Somers radius_put_physical_details(struct rad_handle *rad, struct physical *p) 769de59e178SBrian Somers { 770de59e178SBrian Somers int slot, type; 771de59e178SBrian Somers 772de59e178SBrian Somers type = RAD_VIRTUAL; 773de59e178SBrian Somers if (p->handler) 774de59e178SBrian Somers switch (p->handler->type) { 775de59e178SBrian Somers case I4B_DEVICE: 776de59e178SBrian Somers type = RAD_ISDN_SYNC; 777de59e178SBrian Somers break; 778de59e178SBrian Somers 779de59e178SBrian Somers case TTY_DEVICE: 780de59e178SBrian Somers type = RAD_ASYNC; 781de59e178SBrian Somers break; 782de59e178SBrian Somers 783de59e178SBrian Somers case ETHER_DEVICE: 784de59e178SBrian Somers type = RAD_ETHERNET; 785de59e178SBrian Somers break; 786de59e178SBrian Somers 787de59e178SBrian Somers case TCP_DEVICE: 788de59e178SBrian Somers case UDP_DEVICE: 789de59e178SBrian Somers case EXEC_DEVICE: 790de59e178SBrian Somers case ATM_DEVICE: 791de59e178SBrian Somers case NG_DEVICE: 792de59e178SBrian Somers type = RAD_VIRTUAL; 793de59e178SBrian Somers break; 794de59e178SBrian Somers } 795de59e178SBrian Somers 796de59e178SBrian Somers if (rad_put_int(rad, RAD_NAS_PORT_TYPE, type) != 0) { 797de59e178SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad)); 798de59e178SBrian Somers rad_close(rad); 799de59e178SBrian Somers return 0; 800de59e178SBrian Somers } 801de59e178SBrian Somers 802de59e178SBrian Somers if ((slot = physical_Slot(p)) >= 0) 803de59e178SBrian Somers if (rad_put_int(rad, RAD_NAS_PORT, slot) != 0) { 804de59e178SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad)); 805de59e178SBrian Somers rad_close(rad); 806de59e178SBrian Somers return 0; 807de59e178SBrian Somers } 808de59e178SBrian Somers 809de59e178SBrian Somers return 1; 810de59e178SBrian Somers } 811de59e178SBrian Somers 812f0cdd9c0SBrian Somers /* 813f0cdd9c0SBrian Somers * Start an authentication request to the RADIUS server. 814f0cdd9c0SBrian Somers */ 815a16061b2SBrian Somers int 816f0cdd9c0SBrian Somers radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, 817a16061b2SBrian Somers const char *key, int klen, const char *nchallenge, 818250be50bSBrian Somers int nclen) 819f0cdd9c0SBrian Somers { 820f0cdd9c0SBrian Somers struct timeval tv; 821de59e178SBrian Somers int got; 82226e6a622SBrian Somers char hostname[MAXHOSTNAMELEN]; 823aadbb4eaSBrian Somers #if 0 824f10f5203SBrian Somers struct hostent *hp; 825f10f5203SBrian Somers struct in_addr hostaddr; 8268fb5ef5aSBrian Somers #endif 827ff8e577bSBrian Somers #ifndef NODES 828a16061b2SBrian Somers struct mschap_response msresp; 829a16061b2SBrian Somers struct mschap2_response msresp2; 830250be50bSBrian Somers const struct MSCHAPv2_resp *keyv2; 831ff8e577bSBrian Somers #endif 832f0cdd9c0SBrian Somers 833f0cdd9c0SBrian Somers if (!*r->cfg.file) 834a16061b2SBrian Somers return 0; 835f0cdd9c0SBrian Somers 836f0cdd9c0SBrian Somers if (r->cx.fd != -1) 837f0cdd9c0SBrian Somers /* 838f0cdd9c0SBrian Somers * We assume that our name/key/challenge is the same as last time, 839f0cdd9c0SBrian Somers * and just continue to wait for the RADIUS server(s). 840f0cdd9c0SBrian Somers */ 841a16061b2SBrian Somers return 1; 842f0cdd9c0SBrian Somers 843f0cdd9c0SBrian Somers radius_Destroy(r); 844f0cdd9c0SBrian Somers 845794c9bbcSBrian Somers if ((r->cx.rad = rad_auth_open()) == NULL) { 846794c9bbcSBrian Somers log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 847a16061b2SBrian Somers return 0; 848f0cdd9c0SBrian Somers } 849f0cdd9c0SBrian Somers 850f0cdd9c0SBrian Somers if (rad_config(r->cx.rad, r->cfg.file) != 0) { 851f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 852f0cdd9c0SBrian Somers rad_close(r->cx.rad); 853a16061b2SBrian Somers return 0; 854f0cdd9c0SBrian Somers } 855f0cdd9c0SBrian Somers 856f0cdd9c0SBrian Somers if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) { 857f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 858f0cdd9c0SBrian Somers rad_close(r->cx.rad); 859a16061b2SBrian Somers return 0; 860f0cdd9c0SBrian Somers } 861f0cdd9c0SBrian Somers 8624dc4e1eeSBrian Somers if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 || 863f0cdd9c0SBrian Somers rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 864f0cdd9c0SBrian Somers rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 865f0cdd9c0SBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 866f0cdd9c0SBrian Somers rad_close(r->cx.rad); 867a16061b2SBrian Somers return 0; 868f0cdd9c0SBrian Somers } 869f0cdd9c0SBrian Somers 870ff8e577bSBrian Somers switch (authp->physical->link.lcp.want_auth) { 871ff8e577bSBrian Somers case PROTO_PAP: 872ff8e577bSBrian Somers /* We're talking PAP */ 873ff8e577bSBrian Somers if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) { 874ff8e577bSBrian Somers log_Printf(LogERROR, "PAP: rad_put_string: %s\n", 875ff8e577bSBrian Somers rad_strerror(r->cx.rad)); 876ff8e577bSBrian Somers rad_close(r->cx.rad); 877a16061b2SBrian Somers return 0; 878ff8e577bSBrian Somers } 879ff8e577bSBrian Somers break; 880ff8e577bSBrian Somers 881ff8e577bSBrian Somers case PROTO_CHAP: 882ff8e577bSBrian Somers switch (authp->physical->link.lcp.want_authtype) { 883ff8e577bSBrian Somers case 0x5: 88450ca6ec3SBrian Somers if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 || 885a16061b2SBrian Somers rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) { 886f0cdd9c0SBrian Somers log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", 887f0cdd9c0SBrian Somers rad_strerror(r->cx.rad)); 888f0cdd9c0SBrian Somers rad_close(r->cx.rad); 889a16061b2SBrian Somers return 0; 890f0cdd9c0SBrian Somers } 891ff8e577bSBrian Somers break; 892ff8e577bSBrian Somers 893ff8e577bSBrian Somers #ifndef NODES 894ff8e577bSBrian Somers case 0x80: 895ff8e577bSBrian Somers if (klen != 50) { 896a16061b2SBrian Somers log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen); 897f0cdd9c0SBrian Somers rad_close(r->cx.rad); 898a16061b2SBrian Somers return 0; 899f0cdd9c0SBrian Somers } 900a16061b2SBrian Somers 901ff8e577bSBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 902a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 903a16061b2SBrian Somers msresp.ident = *key; 904a16061b2SBrian Somers msresp.flags = 0x01; 905a16061b2SBrian Somers memcpy(msresp.lm_response, key + 1, 24); 906a16061b2SBrian Somers memcpy(msresp.nt_response, key + 25, 24); 907ff8e577bSBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 908a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp, 909a16061b2SBrian Somers sizeof msresp); 910ff8e577bSBrian Somers break; 911ff8e577bSBrian Somers 912ff8e577bSBrian Somers case 0x81: 913250be50bSBrian Somers if (klen != sizeof(*keyv2) + 1) { 914a16061b2SBrian Somers log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen); 915a16061b2SBrian Somers rad_close(r->cx.rad); 916a16061b2SBrian Somers return 0; 917a16061b2SBrian Somers } 918a16061b2SBrian Somers 919250be50bSBrian Somers keyv2 = (const struct MSCHAPv2_resp *)(key + 1); 920a16061b2SBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 921a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); 922a16061b2SBrian Somers msresp2.ident = *key; 923250be50bSBrian Somers msresp2.flags = keyv2->Flags; 924250be50bSBrian Somers memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response); 925a16061b2SBrian Somers memset(msresp2.reserved, '\0', sizeof msresp2.reserved); 926250be50bSBrian Somers memcpy(msresp2.pchallenge, keyv2->PeerChallenge, 927250be50bSBrian Somers sizeof msresp2.pchallenge); 928a16061b2SBrian Somers rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, 929a16061b2SBrian Somers RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2, 930a16061b2SBrian Somers sizeof msresp2); 931a16061b2SBrian Somers break; 932ff8e577bSBrian Somers #endif 933ff8e577bSBrian Somers default: 934ff8e577bSBrian Somers log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n", 935ff8e577bSBrian Somers authp->physical->link.lcp.want_authtype); 936ff8e577bSBrian Somers rad_close(r->cx.rad); 937a16061b2SBrian Somers return 0; 938ff8e577bSBrian Somers } 939ff8e577bSBrian Somers } 940f0cdd9c0SBrian Somers 941f10f5203SBrian Somers if (gethostname(hostname, sizeof hostname) != 0) 942f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 943f10f5203SBrian Somers else { 944aadbb4eaSBrian Somers #if 0 945f10f5203SBrian Somers if ((hp = gethostbyname(hostname)) != NULL) { 946f10f5203SBrian Somers hostaddr.s_addr = *(u_long *)hp->h_addr; 947f10f5203SBrian Somers if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 948f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 949f10f5203SBrian Somers rad_strerror(r->cx.rad)); 950f10f5203SBrian Somers rad_close(r->cx.rad); 951a16061b2SBrian Somers return 0; 952f10f5203SBrian Somers } 953f10f5203SBrian Somers } 954aadbb4eaSBrian Somers #endif 955f10f5203SBrian Somers if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 956f10f5203SBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 957f10f5203SBrian Somers rad_strerror(r->cx.rad)); 958f10f5203SBrian Somers rad_close(r->cx.rad); 959a16061b2SBrian Somers return 0; 960f10f5203SBrian Somers } 961f10f5203SBrian Somers } 962f10f5203SBrian Somers 963de59e178SBrian Somers radius_put_physical_details(r->cx.rad, authp->physical); 964f10f5203SBrian Somers 965c42627ffSBrian Somers r->cx.auth = authp; 966f0cdd9c0SBrian Somers if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 967f0cdd9c0SBrian Somers radius_Process(r, got); 968f0cdd9c0SBrian Somers else { 969f0cdd9c0SBrian Somers log_Printf(LogPHASE, "Radius: Request sent\n"); 970f0cdd9c0SBrian Somers log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 971f0cdd9c0SBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 972f0cdd9c0SBrian Somers r->cx.timer.func = radius_Timeout; 973c42627ffSBrian Somers r->cx.timer.name = "radius auth"; 974f0cdd9c0SBrian Somers r->cx.timer.arg = r; 975f0cdd9c0SBrian Somers timer_Start(&r->cx.timer); 976f0cdd9c0SBrian Somers } 977a16061b2SBrian Somers 978a16061b2SBrian Somers return 1; 979f0cdd9c0SBrian Somers } 980f0cdd9c0SBrian Somers 981cf7c10d0SHajimu UMEMOTO /* Fetch IP, netmask from IPCP */ 982cf7c10d0SHajimu UMEMOTO void 983cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ip(struct radacct *ac, struct in_addr *peer_ip, 984cf7c10d0SHajimu UMEMOTO struct in_addr *netmask) 985cf7c10d0SHajimu UMEMOTO { 986cf7c10d0SHajimu UMEMOTO ac->proto = PROTO_IPCP; 9872cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ip.addr, peer_ip, sizeof(ac->peer.ip.addr)); 9882cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ip.mask, netmask, sizeof(ac->peer.ip.mask)); 989cf7c10d0SHajimu UMEMOTO } 990cf7c10d0SHajimu UMEMOTO 991cf7c10d0SHajimu UMEMOTO #ifndef NOINET6 992cf7c10d0SHajimu UMEMOTO /* Fetch interface-id from IPV6CP */ 993cf7c10d0SHajimu UMEMOTO void 994cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ipv6(struct radacct *ac, u_char *ifid) 995cf7c10d0SHajimu UMEMOTO { 996cf7c10d0SHajimu UMEMOTO ac->proto = PROTO_IPV6CP; 9972cc2a59dSHajimu UMEMOTO memcpy(&ac->peer.ipv6.ifid, ifid, sizeof(ac->peer.ipv6.ifid)); 998cf7c10d0SHajimu UMEMOTO } 999cf7c10d0SHajimu UMEMOTO #endif 1000cf7c10d0SHajimu UMEMOTO 1001f0cdd9c0SBrian Somers /* 1002794c9bbcSBrian Somers * Send an accounting request to the RADIUS server 1003794c9bbcSBrian Somers */ 1004794c9bbcSBrian Somers void 1005794c9bbcSBrian Somers radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl, 1006cf7c10d0SHajimu UMEMOTO int acct_type, struct pppThroughput *stats) 1007794c9bbcSBrian Somers { 1008794c9bbcSBrian Somers struct timeval tv; 1009de59e178SBrian Somers int got; 101026e6a622SBrian Somers char hostname[MAXHOSTNAMELEN]; 1011aadbb4eaSBrian Somers #if 0 1012794c9bbcSBrian Somers struct hostent *hp; 1013794c9bbcSBrian Somers struct in_addr hostaddr; 10148fb5ef5aSBrian Somers #endif 1015794c9bbcSBrian Somers 1016794c9bbcSBrian Somers if (!*r->cfg.file) 1017794c9bbcSBrian Somers return; 1018794c9bbcSBrian Somers 1019794c9bbcSBrian Somers if (r->cx.fd != -1) 1020794c9bbcSBrian Somers /* 1021794c9bbcSBrian Somers * We assume that our name/key/challenge is the same as last time, 1022794c9bbcSBrian Somers * and just continue to wait for the RADIUS server(s). 1023794c9bbcSBrian Somers */ 1024794c9bbcSBrian Somers return; 1025794c9bbcSBrian Somers 10268fb5ef5aSBrian Somers timer_Stop(&r->cx.timer); 1027794c9bbcSBrian Somers 1028ba093e81SBrian Somers if ((r->cx.rad = rad_acct_open()) == NULL) { 1029794c9bbcSBrian Somers log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 1030794c9bbcSBrian Somers return; 1031794c9bbcSBrian Somers } 1032794c9bbcSBrian Somers 1033794c9bbcSBrian Somers if (rad_config(r->cx.rad, r->cfg.file) != 0) { 1034794c9bbcSBrian Somers log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 1035794c9bbcSBrian Somers rad_close(r->cx.rad); 1036794c9bbcSBrian Somers return; 1037794c9bbcSBrian Somers } 1038794c9bbcSBrian Somers 1039794c9bbcSBrian Somers if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) { 1040794c9bbcSBrian Somers log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 1041794c9bbcSBrian Somers rad_close(r->cx.rad); 1042794c9bbcSBrian Somers return; 1043794c9bbcSBrian Somers } 1044794c9bbcSBrian Somers 1045794c9bbcSBrian Somers /* Grab some accounting data and initialize structure */ 1046794c9bbcSBrian Somers if (acct_type == RAD_START) { 1047794c9bbcSBrian Somers ac->rad_parent = r; 1048794c9bbcSBrian Somers /* Fetch username from datalink */ 10494dc4e1eeSBrian Somers strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name); 1050794c9bbcSBrian Somers ac->user_name[AUTHLEN-1] = '\0'; 1051794c9bbcSBrian Somers 1052794c9bbcSBrian Somers ac->authentic = 2; /* Assume RADIUS verified auth data */ 1053794c9bbcSBrian Somers 1054794c9bbcSBrian Somers /* Generate a session ID */ 105512b5aabaSBrian Somers snprintf(ac->session_id, sizeof ac->session_id, "%s%ld-%s%lu", 105612b5aabaSBrian Somers dl->bundle->cfg.auth.name, (long)getpid(), 10574dc4e1eeSBrian Somers dl->peer.authname, (unsigned long)stats->uptime); 1058794c9bbcSBrian Somers 1059794c9bbcSBrian Somers /* And grab our MP socket name */ 1060794c9bbcSBrian Somers snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s", 1061794c9bbcSBrian Somers dl->bundle->ncp.mp.active ? 1062794c9bbcSBrian Somers dl->bundle->ncp.mp.server.socket.sun_path : ""); 1063794c9bbcSBrian Somers }; 1064794c9bbcSBrian Somers 1065794c9bbcSBrian Somers if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 || 1066794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 1067cf7c10d0SHajimu UMEMOTO rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 1068794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1069794c9bbcSBrian Somers rad_close(r->cx.rad); 1070794c9bbcSBrian Somers return; 1071794c9bbcSBrian Somers } 1072cf7c10d0SHajimu UMEMOTO switch (ac->proto) { 1073cf7c10d0SHajimu UMEMOTO case PROTO_IPCP: 10742cc2a59dSHajimu UMEMOTO if (rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS, 10752cc2a59dSHajimu UMEMOTO ac->peer.ip.addr) != 0 || \ 10762cc2a59dSHajimu UMEMOTO rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK, 10772cc2a59dSHajimu UMEMOTO ac->peer.ip.mask) != 0) { 1078cf7c10d0SHajimu UMEMOTO log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1079cf7c10d0SHajimu UMEMOTO rad_close(r->cx.rad); 1080cf7c10d0SHajimu UMEMOTO return; 1081cf7c10d0SHajimu UMEMOTO } 1082cf7c10d0SHajimu UMEMOTO break; 1083cf7c10d0SHajimu UMEMOTO #ifndef NOINET6 1084cf7c10d0SHajimu UMEMOTO case PROTO_IPV6CP: 10852cc2a59dSHajimu UMEMOTO if (rad_put_attr(r->cx.rad, RAD_FRAMED_INTERFACE_ID, ac->peer.ipv6.ifid, 10862cc2a59dSHajimu UMEMOTO sizeof(ac->peer.ipv6.ifid)) != 0) { 1087cf7c10d0SHajimu UMEMOTO log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad)); 1088cf7c10d0SHajimu UMEMOTO rad_close(r->cx.rad); 1089cf7c10d0SHajimu UMEMOTO return; 1090cf7c10d0SHajimu UMEMOTO } 1091ec3e98b8SHajimu UMEMOTO if (r->ipv6prefix) { 1092ec3e98b8SHajimu UMEMOTO /* 1093ec3e98b8SHajimu UMEMOTO * Since PPP doesn't delegate an IPv6 prefix to a peer, 1094ec3e98b8SHajimu UMEMOTO * Framed-IPv6-Prefix may be not used, actually. 1095ec3e98b8SHajimu UMEMOTO */ 1096ec3e98b8SHajimu UMEMOTO if (rad_put_attr(r->cx.rad, RAD_FRAMED_IPV6_PREFIX, r->ipv6prefix, 1097ec3e98b8SHajimu UMEMOTO sizeof(struct in6_addr) + 2) != 0) { 1098ec3e98b8SHajimu UMEMOTO log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad)); 1099ec3e98b8SHajimu UMEMOTO rad_close(r->cx.rad); 1100ec3e98b8SHajimu UMEMOTO return; 1101ec3e98b8SHajimu UMEMOTO } 1102ec3e98b8SHajimu UMEMOTO } 1103cf7c10d0SHajimu UMEMOTO break; 1104cf7c10d0SHajimu UMEMOTO #endif 1105cf7c10d0SHajimu UMEMOTO default: 1106cf7c10d0SHajimu UMEMOTO /* We don't log any protocol specific information */ 1107cf7c10d0SHajimu UMEMOTO break; 1108cf7c10d0SHajimu UMEMOTO } 1109794c9bbcSBrian Somers 1110794c9bbcSBrian Somers if (gethostname(hostname, sizeof hostname) != 0) 1111794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 1112794c9bbcSBrian Somers else { 1113aadbb4eaSBrian Somers #if 0 1114794c9bbcSBrian Somers if ((hp = gethostbyname(hostname)) != NULL) { 1115794c9bbcSBrian Somers hostaddr.s_addr = *(u_long *)hp->h_addr; 1116794c9bbcSBrian Somers if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 1117794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1118794c9bbcSBrian Somers rad_strerror(r->cx.rad)); 1119794c9bbcSBrian Somers rad_close(r->cx.rad); 1120794c9bbcSBrian Somers return; 1121794c9bbcSBrian Somers } 1122794c9bbcSBrian Somers } 1123aadbb4eaSBrian Somers #endif 1124794c9bbcSBrian Somers if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 1125794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 1126794c9bbcSBrian Somers rad_strerror(r->cx.rad)); 1127794c9bbcSBrian Somers rad_close(r->cx.rad); 1128794c9bbcSBrian Somers return; 1129794c9bbcSBrian Somers } 1130794c9bbcSBrian Somers } 1131794c9bbcSBrian Somers 1132de59e178SBrian Somers radius_put_physical_details(r->cx.rad, dl->physical); 1133794c9bbcSBrian Somers 1134794c9bbcSBrian Somers if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 || 1135794c9bbcSBrian Somers rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 || 1136794c9bbcSBrian Somers rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID, 1137794c9bbcSBrian Somers ac->multi_session_id) != 0 || 1138794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) { 1139794c9bbcSBrian Somers /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */ 1140794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1141794c9bbcSBrian Somers rad_close(r->cx.rad); 1142794c9bbcSBrian Somers return; 1143794c9bbcSBrian Somers } 1144794c9bbcSBrian Somers 1145794c9bbcSBrian Somers if (acct_type == RAD_STOP) 1146794c9bbcSBrian Somers /* Show some statistics */ 1147794c9bbcSBrian Somers if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn) != 0 || 1148794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 || 1149794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut) != 0 || 1150794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut) 1151794c9bbcSBrian Somers != 0 || 1152794c9bbcSBrian Somers rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats)) 1153794c9bbcSBrian Somers != 0) { 1154794c9bbcSBrian Somers log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 1155794c9bbcSBrian Somers rad_close(r->cx.rad); 1156794c9bbcSBrian Somers return; 1157794c9bbcSBrian Somers } 1158794c9bbcSBrian Somers 1159c42627ffSBrian Somers r->cx.auth = NULL; /* Not valid for accounting requests */ 1160794c9bbcSBrian Somers if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 1161794c9bbcSBrian Somers radius_Process(r, got); 1162794c9bbcSBrian Somers else { 1163794c9bbcSBrian Somers log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 1164794c9bbcSBrian Somers r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 1165794c9bbcSBrian Somers r->cx.timer.func = radius_Timeout; 1166c42627ffSBrian Somers r->cx.timer.name = "radius acct"; 1167794c9bbcSBrian Somers r->cx.timer.arg = r; 1168794c9bbcSBrian Somers timer_Start(&r->cx.timer); 1169794c9bbcSBrian Somers } 1170794c9bbcSBrian Somers } 1171794c9bbcSBrian Somers 1172794c9bbcSBrian Somers /* 1173f0cdd9c0SBrian Somers * How do things look at the moment ? 1174f0cdd9c0SBrian Somers */ 1175972a1bcfSBrian Somers void 1176972a1bcfSBrian Somers radius_Show(struct radius *r, struct prompt *p) 1177972a1bcfSBrian Somers { 117874457d3dSBrian Somers prompt_Printf(p, " Radius config: %s", 117974457d3dSBrian Somers *r->cfg.file ? r->cfg.file : "none"); 1180972a1bcfSBrian Somers if (r->valid) { 1181972a1bcfSBrian Somers prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip)); 1182972a1bcfSBrian Somers prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask)); 1183972a1bcfSBrian Somers prompt_Printf(p, " MTU: %lu\n", r->mtu); 1184972a1bcfSBrian Somers prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis"); 1185ff8e577bSBrian Somers prompt_Printf(p, " Message: %s\n", r->repstr ? r->repstr : ""); 11868fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Enc Policy: %s\n", 11878fb5ef5aSBrian Somers radius_policyname(r->mppe.policy)); 11888fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Enc Types: %s\n", 11898fb5ef5aSBrian Somers radius_typesname(r->mppe.types)); 11908fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Recv Key: %seceived\n", 11918fb5ef5aSBrian Somers r->mppe.recvkey ? "R" : "Not r"); 11928fb5ef5aSBrian Somers prompt_Printf(p, " MPPE Send Key: %seceived\n", 11938fb5ef5aSBrian Somers r->mppe.sendkey ? "R" : "Not r"); 1194a16061b2SBrian Somers prompt_Printf(p, " MS-CHAP2-Response: %s\n", 1195a16061b2SBrian Somers r->msrepstr ? r->msrepstr : ""); 1196ff8e577bSBrian Somers prompt_Printf(p, " Error Message: %s\n", r->errstr ? r->errstr : ""); 1197972a1bcfSBrian Somers if (r->routes) 1198972a1bcfSBrian Somers route_ShowSticky(p, r->routes, " Routes", 16); 11990fe74aa4SHajimu UMEMOTO #ifndef NOINET6 12000fe74aa4SHajimu UMEMOTO if (r->ipv6routes) 12010fe74aa4SHajimu UMEMOTO route_ShowSticky(p, r->ipv6routes, " IPv6 Routes", 16); 12020fe74aa4SHajimu UMEMOTO #endif 1203972a1bcfSBrian Somers } else 1204972a1bcfSBrian Somers prompt_Printf(p, " (not authenticated)\n"); 1205972a1bcfSBrian Somers } 1206