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/un.h> 36 37 #include <pwd.h> 38 #include <stdio.h> 39 #include <string.h> 40 #include <termios.h> 41 #include <unistd.h> 42 43 #include "layer.h" 44 #include "mbuf.h" 45 #include "defs.h" 46 #include "log.h" 47 #include "timer.h" 48 #include "fsm.h" 49 #include "iplist.h" 50 #include "throughput.h" 51 #include "slcompress.h" 52 #include "lqr.h" 53 #include "hdlc.h" 54 #include "ipcp.h" 55 #include "auth.h" 56 #include "systems.h" 57 #include "lcp.h" 58 #include "ccp.h" 59 #include "link.h" 60 #include "descriptor.h" 61 #include "chat.h" 62 #include "proto.h" 63 #include "filter.h" 64 #include "mp.h" 65 #ifndef NORADIUS 66 #include "radius.h" 67 #endif 68 #include "cbcp.h" 69 #include "chap.h" 70 #include "async.h" 71 #include "physical.h" 72 #include "datalink.h" 73 #include "bundle.h" 74 75 const char * 76 Auth2Nam(u_short auth, u_char type) 77 { 78 static char chap[10]; 79 80 switch (auth) { 81 case PROTO_PAP: 82 return "PAP"; 83 case PROTO_CHAP: 84 snprintf(chap, sizeof chap, "CHAP 0x%02x", type); 85 return chap; 86 case 0: 87 return "none"; 88 } 89 return "unknown"; 90 } 91 92 static int 93 auth_CheckPasswd(const char *name, const char *data, const char *key) 94 { 95 if (!strcmp(data, "*")) { 96 /* Then look up the real password database */ 97 struct passwd *pw; 98 int result; 99 100 result = (pw = getpwnam(name)) && 101 !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd); 102 endpwent(); 103 return result; 104 } 105 106 return !strcmp(data, key); 107 } 108 109 int 110 auth_SetPhoneList(const char *name, char *phone, int phonelen) 111 { 112 FILE *fp; 113 int n, lineno; 114 char *vector[6]; 115 char buff[LINE_LEN]; 116 117 fp = OpenSecret(SECRETFILE); 118 lineno = 0; 119 if (fp != NULL) { 120 while (fgets(buff, sizeof buff, fp)) { 121 lineno++; 122 if (buff[0] == '#') 123 continue; 124 buff[strlen(buff) - 1] = '\0'; 125 memset(vector, '\0', sizeof vector); 126 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0) 127 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 128 if (n < 5) 129 continue; 130 if (strcmp(vector[0], name) == 0) { 131 CloseSecret(fp); 132 if (*vector[4] == '\0') 133 return 0; 134 strncpy(phone, vector[4], phonelen - 1); 135 phone[phonelen - 1] = '\0'; 136 return 1; /* Valid */ 137 } 138 } 139 CloseSecret(fp); 140 } 141 *phone = '\0'; 142 return 0; 143 } 144 145 int 146 auth_Select(struct bundle *bundle, const char *name) 147 { 148 FILE *fp; 149 int n, lineno; 150 char *vector[5]; 151 char buff[LINE_LEN]; 152 153 if (*name == '\0') { 154 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 155 return 1; 156 } 157 158 #ifndef NORADIUS 159 if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE) { 160 /* We've got a radius IP - it overrides everything */ 161 if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip)) 162 return 0; 163 ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr); 164 /* Continue with ppp.secret in case we've got a new label */ 165 } 166 #endif 167 168 fp = OpenSecret(SECRETFILE); 169 lineno = 0; 170 if (fp != NULL) { 171 while (fgets(buff, sizeof buff, fp)) { 172 lineno++; 173 if (buff[0] == '#') 174 continue; 175 buff[strlen(buff) - 1] = '\0'; 176 memset(vector, '\0', sizeof vector); 177 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0) 178 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 179 if (n < 2) 180 continue; 181 if (strcmp(vector[0], name) == 0) { 182 CloseSecret(fp); 183 #ifndef NORADIUS 184 if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) { 185 #endif 186 if (n > 2 && *vector[2] && strcmp(vector[2], "*") && 187 !ipcp_UseHisaddr(bundle, vector[2], 1)) 188 return 0; 189 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 190 #ifndef NORADIUS 191 } 192 #endif 193 if (n > 3 && *vector[3] && strcmp(vector[3], "*")) 194 bundle_SetLabel(bundle, vector[3]); 195 return 1; /* Valid */ 196 } 197 } 198 CloseSecret(fp); 199 } 200 201 #ifndef NOPASSWDAUTH 202 /* Let 'em in anyway - they must have been in the passwd file */ 203 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 204 return 1; 205 #else 206 #ifndef NORADIUS 207 if (bundle->radius.valid) 208 return 1; 209 #endif 210 211 /* Disappeared from ppp.secret ??? */ 212 return 0; 213 #endif 214 } 215 216 int 217 auth_Validate(struct bundle *bundle, const char *name, 218 const char *key, struct physical *physical) 219 { 220 /* Used by PAP routines */ 221 222 FILE *fp; 223 int n, lineno; 224 char *vector[5]; 225 char buff[LINE_LEN]; 226 227 fp = OpenSecret(SECRETFILE); 228 lineno = 0; 229 if (fp != NULL) { 230 while (fgets(buff, sizeof buff, fp)) { 231 lineno++; 232 if (buff[0] == '#') 233 continue; 234 buff[strlen(buff) - 1] = 0; 235 memset(vector, '\0', sizeof vector); 236 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0) 237 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 238 if (n < 2) 239 continue; 240 if (strcmp(vector[0], name) == 0) { 241 CloseSecret(fp); 242 return auth_CheckPasswd(name, vector[1], key); 243 } 244 } 245 CloseSecret(fp); 246 } 247 248 #ifndef NOPASSWDAUTH 249 if (Enabled(bundle, OPT_PASSWDAUTH)) 250 return auth_CheckPasswd(name, "*", key); 251 #endif 252 253 return 0; /* Invalid */ 254 } 255 256 char * 257 auth_GetSecret(struct bundle *bundle, const char *name, int len, 258 struct physical *physical) 259 { 260 /* Used by CHAP routines */ 261 262 FILE *fp; 263 int n, lineno; 264 char *vector[5]; 265 static char buff[LINE_LEN]; /* vector[] will point here when returned */ 266 267 fp = OpenSecret(SECRETFILE); 268 if (fp == NULL) 269 return (NULL); 270 271 lineno = 0; 272 while (fgets(buff, sizeof buff, fp)) { 273 lineno++; 274 if (buff[0] == '#') 275 continue; 276 n = strlen(buff) - 1; 277 if (buff[n] == '\n') 278 buff[n] = '\0'; /* Trim the '\n' */ 279 memset(vector, '\0', sizeof vector); 280 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0) 281 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno); 282 if (n < 2) 283 continue; 284 if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) { 285 CloseSecret(fp); 286 return vector[1]; 287 } 288 } 289 CloseSecret(fp); 290 return (NULL); /* Invalid */ 291 } 292 293 static void 294 AuthTimeout(void *vauthp) 295 { 296 struct authinfo *authp = (struct authinfo *)vauthp; 297 298 timer_Stop(&authp->authtimer); 299 if (--authp->retry > 0) { 300 authp->id++; 301 (*authp->fn.req)(authp); 302 timer_Start(&authp->authtimer); 303 } else { 304 log_Printf(LogPHASE, "Auth: No response from server\n"); 305 datalink_AuthNotOk(authp->physical->dl); 306 } 307 } 308 309 void 310 auth_Init(struct authinfo *authp, struct physical *p, auth_func req, 311 auth_func success, auth_func failure) 312 { 313 memset(authp, '\0', sizeof(struct authinfo)); 314 authp->cfg.fsm.timeout = DEF_FSMRETRY; 315 authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES; 316 authp->cfg.fsm.maxtrm = 0; /* not used */ 317 authp->fn.req = req; 318 authp->fn.success = success; 319 authp->fn.failure = failure; 320 authp->physical = p; 321 } 322 323 void 324 auth_StartReq(struct authinfo *authp) 325 { 326 timer_Stop(&authp->authtimer); 327 authp->authtimer.func = AuthTimeout; 328 authp->authtimer.name = "auth"; 329 authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS; 330 authp->authtimer.arg = (void *)authp; 331 authp->retry = authp->cfg.fsm.maxreq; 332 authp->id = 1; 333 (*authp->fn.req)(authp); 334 timer_Start(&authp->authtimer); 335 } 336 337 void 338 auth_StopTimer(struct authinfo *authp) 339 { 340 timer_Stop(&authp->authtimer); 341 } 342 343 struct mbuf * 344 auth_ReadHeader(struct authinfo *authp, struct mbuf *bp) 345 { 346 int len; 347 348 len = m_length(bp); 349 if (len >= sizeof authp->in.hdr) { 350 bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr); 351 if (len >= ntohs(authp->in.hdr.length)) 352 return bp; 353 authp->in.hdr.length = htons(0); 354 log_Printf(LogWARN, "auth_ReadHeader: Short packet (%d > %d) !\n", 355 ntohs(authp->in.hdr.length), len); 356 } else { 357 authp->in.hdr.length = htons(0); 358 log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%d > %d) !\n", 359 (int)(sizeof authp->in.hdr), len); 360 } 361 362 m_freem(bp); 363 return NULL; 364 } 365 366 struct mbuf * 367 auth_ReadName(struct authinfo *authp, struct mbuf *bp, int len) 368 { 369 if (len > sizeof authp->in.name - 1) 370 log_Printf(LogWARN, "auth_ReadName: Name too long (%d) !\n", len); 371 else { 372 int mlen = m_length(bp); 373 374 if (len > mlen) 375 log_Printf(LogWARN, "auth_ReadName: Short packet (%d > %d) !\n", 376 len, mlen); 377 else { 378 bp = mbuf_Read(bp, (u_char *)authp->in.name, len); 379 authp->in.name[len] = '\0'; 380 return bp; 381 } 382 } 383 384 *authp->in.name = '\0'; 385 m_freem(bp); 386 return NULL; 387 } 388