auth.c revision 44305
1/* 2 * PPP Secret Key Module 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan, Inc. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $Id: auth.c,v 1.41 1999/02/20 01:12:45 brian Exp $ 21 * 22 * TODO: 23 * o Implement check against with registered IP addresses. 24 */ 25#include <sys/param.h> 26#include <netinet/in.h> 27#include <netinet/in_systm.h> 28#include <netinet/ip.h> 29#include <sys/un.h> 30 31#include <pwd.h> 32#include <stdio.h> 33#include <string.h> 34#include <termios.h> 35#include <unistd.h> 36 37#include "mbuf.h" 38#include "defs.h" 39#include "log.h" 40#include "timer.h" 41#include "fsm.h" 42#include "iplist.h" 43#include "throughput.h" 44#include "slcompress.h" 45#include "lqr.h" 46#include "hdlc.h" 47#include "ipcp.h" 48#include "auth.h" 49#include "systems.h" 50#include "lcp.h" 51#include "ccp.h" 52#include "link.h" 53#include "descriptor.h" 54#include "chat.h" 55#include "lcpproto.h" 56#include "filter.h" 57#include "mp.h" 58#ifndef NORADIUS 59#include "radius.h" 60#endif 61#include "cbcp.h" 62#include "chap.h" 63#include "async.h" 64#include "physical.h" 65#include "datalink.h" 66#include "bundle.h" 67 68const char * 69Auth2Nam(u_short auth, u_char type) 70{ 71 static char chap[10]; 72 73 switch (auth) { 74 case PROTO_PAP: 75 return "PAP"; 76 case PROTO_CHAP: 77 snprintf(chap, sizeof chap, "CHAP 0x%02x", type); 78 return chap; 79 case 0: 80 return "none"; 81 } 82 return "unknown"; 83} 84 85static int 86auth_CheckPasswd(const char *name, const char *data, const char *key) 87{ 88 if (!strcmp(data, "*")) { 89 /* Then look up the real password database */ 90 struct passwd *pw; 91 int result; 92 93 result = (pw = getpwnam(name)) && 94 !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd); 95 endpwent(); 96 return result; 97 } 98 99 return !strcmp(data, key); 100} 101 102int 103auth_SetPhoneList(const char *name, char *phone, int phonelen) 104{ 105 FILE *fp; 106 int n; 107 char *vector[6]; 108 char buff[LINE_LEN]; 109 110 fp = OpenSecret(SECRETFILE); 111 if (fp != NULL) { 112 while (fgets(buff, sizeof buff, fp)) { 113 if (buff[0] == '#') 114 continue; 115 buff[strlen(buff) - 1] = '\0'; 116 memset(vector, '\0', sizeof vector); 117 n = MakeArgs(buff, vector, VECSIZE(vector)); 118 if (n < 5) 119 continue; 120 if (strcmp(vector[0], name) == 0) { 121 CloseSecret(fp); 122 if (*vector[4] == '\0') 123 return 0; 124 strncpy(phone, vector[4], phonelen - 1); 125 phone[phonelen - 1] = '\0'; 126 return 1; /* Valid */ 127 } 128 } 129 CloseSecret(fp); 130 } 131 *phone = '\0'; 132 return 0; 133} 134 135int 136auth_Select(struct bundle *bundle, const char *name) 137{ 138 FILE *fp; 139 int n; 140 char *vector[5]; 141 char buff[LINE_LEN]; 142 143 if (*name == '\0') { 144 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 145 return 1; 146 } 147 148#ifndef NORADIUS 149 if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE) { 150 /* We've got a radius IP - it overrides everything */ 151 if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip)) 152 return 0; 153 ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr); 154 /* Continue with ppp.secret in case we've got a new label */ 155 } 156#endif 157 158 fp = OpenSecret(SECRETFILE); 159 if (fp != NULL) { 160 while (fgets(buff, sizeof buff, fp)) { 161 if (buff[0] == '#') 162 continue; 163 buff[strlen(buff) - 1] = '\0'; 164 memset(vector, '\0', sizeof vector); 165 n = MakeArgs(buff, vector, VECSIZE(vector)); 166 if (n < 2) 167 continue; 168 if (strcmp(vector[0], name) == 0) { 169 CloseSecret(fp); 170#ifndef NORADIUS 171 if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) { 172#endif 173 if (n > 2 && *vector[2] && strcmp(vector[2], "*") && 174 !ipcp_UseHisaddr(bundle, vector[2], 1)) 175 return 0; 176 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 177#ifndef NORADIUS 178 } 179#endif 180 if (n > 3 && *vector[3] && strcmp(vector[3], "*")) 181 bundle_SetLabel(bundle, vector[3]); 182 return 1; /* Valid */ 183 } 184 } 185 CloseSecret(fp); 186 } 187 188#ifndef NOPASSWDAUTH 189 /* Let 'em in anyway - they must have been in the passwd file */ 190 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 191 return 1; 192#else 193#ifndef NORADIUS 194 if (bundle->radius.valid) 195 return 1; 196#endif 197 198 /* Disappeared from ppp.secret ??? */ 199 return 0; 200#endif 201} 202 203int 204auth_Validate(struct bundle *bundle, const char *name, 205 const char *key, struct physical *physical) 206{ 207 /* Used by PAP routines */ 208 209 FILE *fp; 210 int n; 211 char *vector[5]; 212 char buff[LINE_LEN]; 213 214 fp = OpenSecret(SECRETFILE); 215 if (fp != NULL) { 216 while (fgets(buff, sizeof buff, fp)) { 217 if (buff[0] == '#') 218 continue; 219 buff[strlen(buff) - 1] = 0; 220 memset(vector, '\0', sizeof vector); 221 n = MakeArgs(buff, vector, VECSIZE(vector)); 222 if (n < 2) 223 continue; 224 if (strcmp(vector[0], name) == 0) { 225 CloseSecret(fp); 226 return auth_CheckPasswd(name, vector[1], key); 227 } 228 } 229 CloseSecret(fp); 230 } 231 232#ifndef NOPASSWDAUTH 233 if (Enabled(bundle, OPT_PASSWDAUTH)) 234 return auth_CheckPasswd(name, "*", key); 235#endif 236 237 return 0; /* Invalid */ 238} 239 240char * 241auth_GetSecret(struct bundle *bundle, const char *name, int len, 242 struct physical *physical) 243{ 244 /* Used by CHAP routines */ 245 246 FILE *fp; 247 int n; 248 char *vector[5]; 249 static char buff[LINE_LEN]; 250 251 fp = OpenSecret(SECRETFILE); 252 if (fp == NULL) 253 return (NULL); 254 255 while (fgets(buff, sizeof buff, fp)) { 256 if (buff[0] == '#') 257 continue; 258 buff[strlen(buff) - 1] = 0; 259 memset(vector, '\0', sizeof vector); 260 n = MakeArgs(buff, vector, VECSIZE(vector)); 261 if (n < 2) 262 continue; 263 if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) { 264 CloseSecret(fp); 265 return vector[1]; 266 } 267 } 268 CloseSecret(fp); 269 return (NULL); /* Invalid */ 270} 271 272static void 273AuthTimeout(void *vauthp) 274{ 275 struct authinfo *authp = (struct authinfo *)vauthp; 276 277 timer_Stop(&authp->authtimer); 278 if (--authp->retry > 0) { 279 authp->id++; 280 (*authp->fn.req)(authp); 281 timer_Start(&authp->authtimer); 282 } else { 283 log_Printf(LogPHASE, "Auth: No response from server\n"); 284 datalink_AuthNotOk(authp->physical->dl); 285 } 286} 287 288void 289auth_Init(struct authinfo *authp, struct physical *p, auth_func req, 290 auth_func success, auth_func failure) 291{ 292 memset(authp, '\0', sizeof(struct authinfo)); 293 authp->cfg.fsm.timeout = DEF_FSMRETRY; 294 authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES; 295 authp->cfg.fsm.maxtrm = 0; /* not used */ 296 authp->fn.req = req; 297 authp->fn.success = success; 298 authp->fn.failure = failure; 299 authp->physical = p; 300} 301 302void 303auth_StartReq(struct authinfo *authp) 304{ 305 timer_Stop(&authp->authtimer); 306 authp->authtimer.func = AuthTimeout; 307 authp->authtimer.name = "auth"; 308 authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS; 309 authp->authtimer.arg = (void *)authp; 310 authp->retry = authp->cfg.fsm.maxreq; 311 authp->id = 1; 312 (*authp->fn.req)(authp); 313 timer_Start(&authp->authtimer); 314} 315 316void 317auth_StopTimer(struct authinfo *authp) 318{ 319 timer_Stop(&authp->authtimer); 320} 321 322struct mbuf * 323auth_ReadHeader(struct authinfo *authp, struct mbuf *bp) 324{ 325 int len; 326 327 len = mbuf_Length(bp); 328 if (len >= sizeof authp->in.hdr) { 329 bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr); 330 if (len >= ntohs(authp->in.hdr.length)) 331 return bp; 332 authp->in.hdr.length = htons(0); 333 log_Printf(LogWARN, "auth_ReadHeader: Short packet (%d > %d) !\n", 334 ntohs(authp->in.hdr.length), len); 335 } else { 336 authp->in.hdr.length = htons(0); 337 log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%d > %d) !\n", 338 sizeof authp->in.hdr, len); 339 } 340 341 mbuf_Free(bp); 342 return NULL; 343} 344 345struct mbuf * 346auth_ReadName(struct authinfo *authp, struct mbuf *bp, int len) 347{ 348 if (len > sizeof authp->in.name - 1) 349 log_Printf(LogWARN, "auth_ReadName: Name too long (%d) !\n", len); 350 else { 351 int mlen = mbuf_Length(bp); 352 353 if (len > mlen) 354 log_Printf(LogWARN, "auth_ReadName: Short packet (%d > %d) !\n", 355 len, mlen); 356 else { 357 bp = mbuf_Read(bp, (u_char *)authp->in.name, len); 358 authp->in.name[len] = '\0'; 359 return bp; 360 } 361 } 362 363 *authp->in.name = '\0'; 364 mbuf_Free(bp); 365 return NULL; 366} 367