auth.c revision 44305
16059Samurai/* 26059Samurai * PPP Secret Key Module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 198857Srgrimes * 2044305Sbrian * $Id: auth.c,v 1.41 1999/02/20 01:12:45 brian Exp $ 218857Srgrimes * 226059Samurai * TODO: 2310528Samurai * o Implement check against with registered IP addresses. 246059Samurai */ 2543313Sbrian#include <sys/param.h> 2630715Sbrian#include <netinet/in.h> 2736285Sbrian#include <netinet/in_systm.h> 2836285Sbrian#include <netinet/ip.h> 2936285Sbrian#include <sys/un.h> 3030715Sbrian 3136285Sbrian#include <pwd.h> 3230715Sbrian#include <stdio.h> 3330715Sbrian#include <string.h> 3443525Sbrian#include <termios.h> 3530715Sbrian#include <unistd.h> 3630715Sbrian 3730715Sbrian#include "mbuf.h" 3830715Sbrian#include "defs.h" 3943525Sbrian#include "log.h" 4030715Sbrian#include "timer.h" 416059Samurai#include "fsm.h" 4236285Sbrian#include "iplist.h" 4336285Sbrian#include "throughput.h" 4436285Sbrian#include "slcompress.h" 4538557Sbrian#include "lqr.h" 4638557Sbrian#include "hdlc.h" 476059Samurai#include "ipcp.h" 486735Samurai#include "auth.h" 4936285Sbrian#include "systems.h" 5036285Sbrian#include "lcp.h" 5136285Sbrian#include "ccp.h" 5236285Sbrian#include "link.h" 5336285Sbrian#include "descriptor.h" 5413389Sphk#include "chat.h" 5536285Sbrian#include "lcpproto.h" 5636285Sbrian#include "filter.h" 5736285Sbrian#include "mp.h" 5843313Sbrian#ifndef NORADIUS 5943313Sbrian#include "radius.h" 6043313Sbrian#endif 6143525Sbrian#include "cbcp.h" 6243525Sbrian#include "chap.h" 6343525Sbrian#include "async.h" 6443525Sbrian#include "physical.h" 6543525Sbrian#include "datalink.h" 6636285Sbrian#include "bundle.h" 676059Samurai 6836285Sbrianconst char * 6944106SbrianAuth2Nam(u_short auth, u_char type) 7013389Sphk{ 7144106Sbrian static char chap[10]; 7244106Sbrian 7336285Sbrian switch (auth) { 7436285Sbrian case PROTO_PAP: 7536285Sbrian return "PAP"; 7636285Sbrian case PROTO_CHAP: 7744106Sbrian snprintf(chap, sizeof chap, "CHAP 0x%02x", type); 7844106Sbrian return chap; 7936285Sbrian case 0: 8036285Sbrian return "none"; 8136285Sbrian } 8236285Sbrian return "unknown"; 836735Samurai} 846735Samurai 8536285Sbrianstatic int 8636285Sbrianauth_CheckPasswd(const char *name, const char *data, const char *key) 8728679Sbrian{ 8836285Sbrian if (!strcmp(data, "*")) { 8936285Sbrian /* Then look up the real password database */ 9036285Sbrian struct passwd *pw; 9136285Sbrian int result; 9236285Sbrian 9336285Sbrian result = (pw = getpwnam(name)) && 9436285Sbrian !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd); 9536285Sbrian endpwent(); 9636285Sbrian return result; 9736285Sbrian } 9836285Sbrian 9936285Sbrian return !strcmp(data, key); 10036285Sbrian} 10136285Sbrian 10236285Sbrianint 10338174Sbrianauth_SetPhoneList(const char *name, char *phone, int phonelen) 10436285Sbrian{ 1056735Samurai FILE *fp; 1066735Samurai int n; 10738174Sbrian char *vector[6]; 10838174Sbrian char buff[LINE_LEN]; 10938174Sbrian 11038174Sbrian fp = OpenSecret(SECRETFILE); 11138174Sbrian if (fp != NULL) { 11238174Sbrian while (fgets(buff, sizeof buff, fp)) { 11338174Sbrian if (buff[0] == '#') 11438174Sbrian continue; 11538174Sbrian buff[strlen(buff) - 1] = '\0'; 11638174Sbrian memset(vector, '\0', sizeof vector); 11738174Sbrian n = MakeArgs(buff, vector, VECSIZE(vector)); 11838174Sbrian if (n < 5) 11938174Sbrian continue; 12038174Sbrian if (strcmp(vector[0], name) == 0) { 12143313Sbrian CloseSecret(fp); 12243313Sbrian if (*vector[4] == '\0') 12338174Sbrian return 0; 12438174Sbrian strncpy(phone, vector[4], phonelen - 1); 12538174Sbrian phone[phonelen - 1] = '\0'; 12643313Sbrian return 1; /* Valid */ 12738174Sbrian } 12838174Sbrian } 12938174Sbrian CloseSecret(fp); 13038174Sbrian } 13138174Sbrian *phone = '\0'; 13238174Sbrian return 0; 13338174Sbrian} 13438174Sbrian 13538174Sbrianint 13638174Sbrianauth_Select(struct bundle *bundle, const char *name) 13738174Sbrian{ 13838174Sbrian FILE *fp; 13938174Sbrian int n; 14036285Sbrian char *vector[5]; 14131070Sbrian char buff[LINE_LEN]; 1426735Samurai 14336285Sbrian if (*name == '\0') { 14443313Sbrian ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 14536285Sbrian return 1; 14636285Sbrian } 14736285Sbrian 14843313Sbrian#ifndef NORADIUS 14943313Sbrian if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE) { 15043313Sbrian /* We've got a radius IP - it overrides everything */ 15143313Sbrian if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip)) 15243313Sbrian return 0; 15343313Sbrian ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr); 15443313Sbrian /* Continue with ppp.secret in case we've got a new label */ 15543313Sbrian } 15643313Sbrian#endif 15743313Sbrian 15836285Sbrian fp = OpenSecret(SECRETFILE); 15936285Sbrian if (fp != NULL) { 16036285Sbrian while (fgets(buff, sizeof buff, fp)) { 16136285Sbrian if (buff[0] == '#') 16236285Sbrian continue; 16337763Sbrian buff[strlen(buff) - 1] = '\0'; 16436285Sbrian memset(vector, '\0', sizeof vector); 16536285Sbrian n = MakeArgs(buff, vector, VECSIZE(vector)); 16636285Sbrian if (n < 2) 16736285Sbrian continue; 16837763Sbrian if (strcmp(vector[0], name) == 0) { 16943313Sbrian CloseSecret(fp); 17043313Sbrian#ifndef NORADIUS 17143313Sbrian if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) { 17243313Sbrian#endif 17343313Sbrian if (n > 2 && *vector[2] && strcmp(vector[2], "*") && 17443313Sbrian !ipcp_UseHisaddr(bundle, vector[2], 1)) 17543313Sbrian return 0; 17643313Sbrian ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 17743313Sbrian#ifndef NORADIUS 17843313Sbrian } 17943313Sbrian#endif 18043313Sbrian if (n > 3 && *vector[3] && strcmp(vector[3], "*")) 18143313Sbrian bundle_SetLabel(bundle, vector[3]); 18243313Sbrian return 1; /* Valid */ 18337763Sbrian } 1846735Samurai } 18536285Sbrian CloseSecret(fp); 1866735Samurai } 18736285Sbrian 18836285Sbrian#ifndef NOPASSWDAUTH 18936285Sbrian /* Let 'em in anyway - they must have been in the passwd file */ 19043313Sbrian ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE); 19136285Sbrian return 1; 19236285Sbrian#else 19343313Sbrian#ifndef NORADIUS 19443313Sbrian if (bundle->radius.valid) 19543313Sbrian return 1; 19643313Sbrian#endif 19743313Sbrian 19843313Sbrian /* Disappeared from ppp.secret ??? */ 19936285Sbrian return 0; 20036285Sbrian#endif 2016735Samurai} 2026735Samurai 2036059Samuraiint 20443313Sbrianauth_Validate(struct bundle *bundle, const char *name, 20536285Sbrian const char *key, struct physical *physical) 2066059Samurai{ 20736285Sbrian /* Used by PAP routines */ 20836285Sbrian 2096059Samurai FILE *fp; 2106059Samurai int n; 21132267Sbrian char *vector[5]; 21231070Sbrian char buff[LINE_LEN]; 2136059Samurai 21436285Sbrian fp = OpenSecret(SECRETFILE); 21536285Sbrian if (fp != NULL) { 21636285Sbrian while (fgets(buff, sizeof buff, fp)) { 21736285Sbrian if (buff[0] == '#') 21836285Sbrian continue; 21936285Sbrian buff[strlen(buff) - 1] = 0; 22036285Sbrian memset(vector, '\0', sizeof vector); 22136285Sbrian n = MakeArgs(buff, vector, VECSIZE(vector)); 22236285Sbrian if (n < 2) 22336285Sbrian continue; 22443313Sbrian if (strcmp(vector[0], name) == 0) { 22543313Sbrian CloseSecret(fp); 22643313Sbrian return auth_CheckPasswd(name, vector[1], key); 2276059Samurai } 2286059Samurai } 22936285Sbrian CloseSecret(fp); 2306059Samurai } 23136285Sbrian 23236285Sbrian#ifndef NOPASSWDAUTH 23336285Sbrian if (Enabled(bundle, OPT_PASSWDAUTH)) 23443313Sbrian return auth_CheckPasswd(name, "*", key); 23536285Sbrian#endif 23636285Sbrian 23736285Sbrian return 0; /* Invalid */ 2386059Samurai} 2396059Samurai 2406059Samuraichar * 24143313Sbrianauth_GetSecret(struct bundle *bundle, const char *name, int len, 24236285Sbrian struct physical *physical) 2436059Samurai{ 24436285Sbrian /* Used by CHAP routines */ 24536285Sbrian 2466059Samurai FILE *fp; 2476059Samurai int n; 24832267Sbrian char *vector[5]; 24941888Sbrian static char buff[LINE_LEN]; 2506059Samurai 25136285Sbrian fp = OpenSecret(SECRETFILE); 2526059Samurai if (fp == NULL) 25328679Sbrian return (NULL); 25436285Sbrian 25531962Sbrian while (fgets(buff, sizeof buff, fp)) { 2566059Samurai if (buff[0] == '#') 2576059Samurai continue; 25828679Sbrian buff[strlen(buff) - 1] = 0; 25931962Sbrian memset(vector, '\0', sizeof vector); 26025560Sbrian n = MakeArgs(buff, vector, VECSIZE(vector)); 2616059Samurai if (n < 2) 2626059Samurai continue; 26343313Sbrian if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) { 26436285Sbrian CloseSecret(fp); 26536285Sbrian return vector[1]; 2666059Samurai } 2676059Samurai } 2686059Samurai CloseSecret(fp); 26928679Sbrian return (NULL); /* Invalid */ 2706059Samurai} 2716735Samurai 2726735Samuraistatic void 27331343SbrianAuthTimeout(void *vauthp) 2746735Samurai{ 27531343Sbrian struct authinfo *authp = (struct authinfo *)vauthp; 2766735Samurai 27736285Sbrian timer_Stop(&authp->authtimer); 2786735Samurai if (--authp->retry > 0) { 27943693Sbrian authp->id++; 28043693Sbrian (*authp->fn.req)(authp); 28136285Sbrian timer_Start(&authp->authtimer); 28243525Sbrian } else { 28343525Sbrian log_Printf(LogPHASE, "Auth: No response from server\n"); 28443525Sbrian datalink_AuthNotOk(authp->physical->dl); 28543525Sbrian } 2866735Samurai} 2876735Samurai 2886735Samuraivoid 28943693Sbrianauth_Init(struct authinfo *authp, struct physical *p, auth_func req, 29043693Sbrian auth_func success, auth_func failure) 2916735Samurai{ 29243693Sbrian memset(authp, '\0', sizeof(struct authinfo)); 29344305Sbrian authp->cfg.fsm.timeout = DEF_FSMRETRY; 29444305Sbrian authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES; 29544305Sbrian authp->cfg.fsm.maxtrm = 0; /* not used */ 29643693Sbrian authp->fn.req = req; 29743693Sbrian authp->fn.success = success; 29843693Sbrian authp->fn.failure = failure; 29943693Sbrian authp->physical = p; 30036285Sbrian} 3016735Samurai 30236285Sbrianvoid 30343693Sbrianauth_StartReq(struct authinfo *authp) 30436285Sbrian{ 30536285Sbrian timer_Stop(&authp->authtimer); 30636285Sbrian authp->authtimer.func = AuthTimeout; 30736285Sbrian authp->authtimer.name = "auth"; 30844305Sbrian authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS; 30943693Sbrian authp->authtimer.arg = (void *)authp; 31044305Sbrian authp->retry = authp->cfg.fsm.maxreq; 3116735Samurai authp->id = 1; 31243693Sbrian (*authp->fn.req)(authp); 31336285Sbrian timer_Start(&authp->authtimer); 3146735Samurai} 3156735Samurai 3166735Samuraivoid 31736285Sbrianauth_StopTimer(struct authinfo *authp) 3186735Samurai{ 31936285Sbrian timer_Stop(&authp->authtimer); 3206735Samurai} 32143693Sbrian 32243693Sbrianstruct mbuf * 32343693Sbrianauth_ReadHeader(struct authinfo *authp, struct mbuf *bp) 32443693Sbrian{ 32543693Sbrian int len; 32643693Sbrian 32743693Sbrian len = mbuf_Length(bp); 32843693Sbrian if (len >= sizeof authp->in.hdr) { 32943693Sbrian bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr); 33043693Sbrian if (len >= ntohs(authp->in.hdr.length)) 33143693Sbrian return bp; 33244159Sbrian authp->in.hdr.length = htons(0); 33344141Sbrian log_Printf(LogWARN, "auth_ReadHeader: Short packet (%d > %d) !\n", 33444141Sbrian ntohs(authp->in.hdr.length), len); 33544159Sbrian } else { 33644159Sbrian authp->in.hdr.length = htons(0); 33744141Sbrian log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%d > %d) !\n", 33844141Sbrian sizeof authp->in.hdr, len); 33944159Sbrian } 34043693Sbrian 34143693Sbrian mbuf_Free(bp); 34243693Sbrian return NULL; 34343693Sbrian} 34443693Sbrian 34543693Sbrianstruct mbuf * 34643693Sbrianauth_ReadName(struct authinfo *authp, struct mbuf *bp, int len) 34743693Sbrian{ 34843693Sbrian if (len > sizeof authp->in.name - 1) 34944141Sbrian log_Printf(LogWARN, "auth_ReadName: Name too long (%d) !\n", len); 35043693Sbrian else { 35143693Sbrian int mlen = mbuf_Length(bp); 35243693Sbrian 35343693Sbrian if (len > mlen) 35444141Sbrian log_Printf(LogWARN, "auth_ReadName: Short packet (%d > %d) !\n", 35544141Sbrian len, mlen); 35643693Sbrian else { 35743693Sbrian bp = mbuf_Read(bp, (u_char *)authp->in.name, len); 35843693Sbrian authp->in.name[len] = '\0'; 35943693Sbrian return bp; 36043693Sbrian } 36143693Sbrian } 36243693Sbrian 36343693Sbrian *authp->in.name = '\0'; 36443693Sbrian mbuf_Free(bp); 36543693Sbrian return NULL; 36643693Sbrian} 367