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