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