1 /*- 2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 4 * Internet Initiative Japan, Inc (IIJ) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <netinet/in.h> 33 #include <netinet/in_systm.h> 34 #include <netinet/ip.h> 35 #include <sys/socket.h> 36 #include <sys/un.h> 37 38 #include <pwd.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include <termios.h> 42 #include <unistd.h> 43 44 #include "layer.h" 45 #include "mbuf.h" 46 #include "defs.h" 47 #include "log.h" 48 #include "timer.h" 49 #include "fsm.h" 50 #include "iplist.h" 51 #include "throughput.h" 52 #include "slcompress.h" 53 #include "lqr.h" 54 #include "hdlc.h" 55 #include "ncpaddr.h" 56 #include "ip.h" 57 #include "ipcp.h" 58 #include "auth.h" 59 #include "systems.h" 60 #include "lcp.h" 61 #include "ccp.h" 62 #include "link.h" 63 #include "descriptor.h" 64 #include "chat.h" 65 #include "proto.h" 66 #include "filter.h" 67 #include "mp.h" 68 #ifndef NORADIUS 69 #include "radius.h" 70 #endif 71 #include "cbcp.h" 72 #include "chap.h" 73 #include "async.h" 74 #include "physical.h" 75 #include "datalink.h" 76 #include "ipv6cp.h" 77 #include "ncp.h" 78 #include "bundle.h" 79 80 const char * 81 Auth2Nam(u_short auth, u_char type) 82 { 83 static char chap[10]; 84 85 switch (auth) { 86 case PROTO_PAP: 87 return "PAP"; 88 case PROTO_CHAP: 89 snprintf(chap, sizeof chap, "CHAP 0x%02x", type); 90 return chap; 91 case 0: 92 return "none"; 93 } 94 return "unknown"; 95 } 96 97 static int 98 auth_CheckPasswd(const char *name, const char *data, const char *key) 99 { 100 if (!strcmp(data, "*")) { 101 /* Then look up the real password database */ 102 struct passwd *pw; 103 int result; 104 105 result = (pw = getpwnam(name)) && 106 !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd); 107 endpwent(); 108 return result; 109 } 110 111 return !strcmp(data, key); 112 } 113 114 int 115 auth_SetPhoneList(const char *name, char *phone, int phonelen) 116 { 117 FILE *fp; 118 int n, lineno; 119 char *vector[6]; 120 char buff[LINE_LEN]; 121 122 fp = OpenSecret(SECRETFILE); 123 lineno = 0; 124 if (fp != NULL) { 125 while (fgets(buff, sizeof buff, fp)) { 126 lineno++; 127 if (buff[0] == '#') 128 continue; 129 buff[strlen(buff) - 1] = '\0'; 130 memset(vector, '\0', sizeof vector); 131 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0) 132 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 133 if (n < 5) 134 continue; 135 if (strcmp(vector[0], name) == 0) { 136 CloseSecret(fp); 137 if (*vector[4] == '\0') 138 return 0; 139 strncpy(phone, vector[4], phonelen - 1); 140 phone[phonelen - 1] = '\0'; 141 return 1; /* Valid */ 142 } 143 } 144 CloseSecret(fp); 145 } 146 *phone = '\0'; 147 return 0; 148 } 149 150 int 151 auth_Select(struct bundle *bundle, const char *name) 152 { 153 FILE *fp; 154 int n, lineno; 155 char *vector[5]; 156 char buff[LINE_LEN]; 157 158 if (*name == '\0') { 159 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 160 return 1; 161 } 162 163 #ifndef NORADIUS 164 if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE) { 165 /* We've got a radius IP - it overrides everything */ 166 if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip)) 167 return 0; 168 ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr); 169 /* Continue with ppp.secret in case we've got a new label */ 170 } 171 #endif 172 173 fp = OpenSecret(SECRETFILE); 174 lineno = 0; 175 if (fp != NULL) { 176 while (fgets(buff, sizeof buff, fp)) { 177 lineno++; 178 if (buff[0] == '#') 179 continue; 180 buff[strlen(buff) - 1] = '\0'; 181 memset(vector, '\0', sizeof vector); 182 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0) 183 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 184 if (n < 2) 185 continue; 186 if (strcmp(vector[0], name) == 0) { 187 CloseSecret(fp); 188 #ifndef NORADIUS 189 if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) { 190 #endif 191 if (n > 2 && *vector[2] && strcmp(vector[2], "*") && 192 !ipcp_UseHisaddr(bundle, vector[2], 1)) 193 return 0; 194 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 195 #ifndef NORADIUS 196 } 197 #endif 198 if (n > 3 && *vector[3] && strcmp(vector[3], "*")) 199 bundle_SetLabel(bundle, vector[3]); 200 return 1; /* Valid */ 201 } 202 } 203 CloseSecret(fp); 204 } 205 206 #ifndef NOPASSWDAUTH 207 /* Let 'em in anyway - they must have been in the passwd file */ 208 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 209 return 1; 210 #else 211 #ifndef NORADIUS 212 if (bundle->radius.valid) 213 return 1; 214 #endif 215 216 /* Disappeared from ppp.secret ??? */ 217 return 0; 218 #endif 219 } 220 221 int 222 auth_Validate(struct bundle *bundle, const char *name, 223 const char *key, struct physical *physical) 224 { 225 /* Used by PAP routines */ 226 227 FILE *fp; 228 int n, lineno; 229 char *vector[5]; 230 char buff[LINE_LEN]; 231 232 fp = OpenSecret(SECRETFILE); 233 lineno = 0; 234 if (fp != NULL) { 235 while (fgets(buff, sizeof buff, fp)) { 236 lineno++; 237 if (buff[0] == '#') 238 continue; 239 buff[strlen(buff) - 1] = 0; 240 memset(vector, '\0', sizeof vector); 241 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0) 242 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 243 if (n < 2) 244 continue; 245 if (strcmp(vector[0], name) == 0) { 246 CloseSecret(fp); 247 return auth_CheckPasswd(name, vector[1], key); 248 } 249 } 250 CloseSecret(fp); 251 } 252 253 #ifndef NOPASSWDAUTH 254 if (Enabled(bundle, OPT_PASSWDAUTH)) 255 return auth_CheckPasswd(name, "*", key); 256 #endif 257 258 return 0; /* Invalid */ 259 } 260 261 char * 262 auth_GetSecret(struct bundle *bundle, const char *name, int len, 263 struct physical *physical) 264 { 265 /* Used by CHAP routines */ 266 267 FILE *fp; 268 int n, lineno; 269 char *vector[5]; 270 static char buff[LINE_LEN]; /* vector[] will point here when returned */ 271 272 fp = OpenSecret(SECRETFILE); 273 if (fp == NULL) 274 return (NULL); 275 276 lineno = 0; 277 while (fgets(buff, sizeof buff, fp)) { 278 lineno++; 279 if (buff[0] == '#') 280 continue; 281 n = strlen(buff) - 1; 282 if (buff[n] == '\n') 283 buff[n] = '\0'; /* Trim the '\n' */ 284 memset(vector, '\0', sizeof vector); 285 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0) 286 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 287 if (n < 2) 288 continue; 289 if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) { 290 CloseSecret(fp); 291 return vector[1]; 292 } 293 } 294 CloseSecret(fp); 295 return (NULL); /* Invalid */ 296 } 297 298 static void 299 AuthTimeout(void *vauthp) 300 { 301 struct authinfo *authp = (struct authinfo *)vauthp; 302 303 timer_Stop(&authp->authtimer); 304 if (--authp->retry > 0) { 305 authp->id++; 306 (*authp->fn.req)(authp); 307 timer_Start(&authp->authtimer); 308 } else { 309 log_Printf(LogPHASE, "Auth: No response from server\n"); 310 datalink_AuthNotOk(authp->physical->dl); 311 } 312 } 313 314 void 315 auth_Init(struct authinfo *authp, struct physical *p, auth_func req, 316 auth_func success, auth_func failure) 317 { 318 memset(authp, '\0', sizeof(struct authinfo)); 319 authp->cfg.fsm.timeout = DEF_FSMRETRY; 320 authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES; 321 authp->cfg.fsm.maxtrm = 0; /* not used */ 322 authp->fn.req = req; 323 authp->fn.success = success; 324 authp->fn.failure = failure; 325 authp->physical = p; 326 } 327 328 void 329 auth_StartReq(struct authinfo *authp) 330 { 331 timer_Stop(&authp->authtimer); 332 authp->authtimer.func = AuthTimeout; 333 authp->authtimer.name = "auth"; 334 authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS; 335 authp->authtimer.arg = (void *)authp; 336 authp->retry = authp->cfg.fsm.maxreq; 337 authp->id = 1; 338 (*authp->fn.req)(authp); 339 timer_Start(&authp->authtimer); 340 } 341 342 void 343 auth_StopTimer(struct authinfo *authp) 344 { 345 timer_Stop(&authp->authtimer); 346 } 347 348 struct mbuf * 349 auth_ReadHeader(struct authinfo *authp, struct mbuf *bp) 350 { 351 int len; 352 353 len = m_length(bp); 354 if (len >= sizeof authp->in.hdr) { 355 bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr); 356 if (len >= ntohs(authp->in.hdr.length)) 357 return bp; 358 authp->in.hdr.length = htons(0); 359 log_Printf(LogWARN, "auth_ReadHeader: Short packet (%d > %d) !\n", 360 ntohs(authp->in.hdr.length), len); 361 } else { 362 authp->in.hdr.length = htons(0); 363 log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%d > %d) !\n", 364 (int)(sizeof authp->in.hdr), len); 365 } 366 367 m_freem(bp); 368 return NULL; 369 } 370 371 struct mbuf * 372 auth_ReadName(struct authinfo *authp, struct mbuf *bp, int len) 373 { 374 if (len > sizeof authp->in.name - 1) 375 log_Printf(LogWARN, "auth_ReadName: Name too long (%d) !\n", len); 376 else { 377 int mlen = m_length(bp); 378 379 if (len > mlen) 380 log_Printf(LogWARN, "auth_ReadName: Short packet (%d > %d) !\n", 381 len, mlen); 382 else { 383 bp = mbuf_Read(bp, (u_char *)authp->in.name, len); 384 authp->in.name[len] = '\0'; 385 return bp; 386 } 387 } 388 389 *authp->in.name = '\0'; 390 m_freem(bp); 391 return NULL; 392 } 393