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