xref: /freebsd/usr.sbin/ppp/auth.c (revision c39aa54ec8245817e058c8493f4cf7236bf24a96)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *			PPP Secret Key Module
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan, Inc.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
2097d92980SPeter Wemm  * $FreeBSD$
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *	TODO:
23c3899f8dSAtsushi Murai  *		o Implement check against with registered IP addresses.
24af57ed9fSAtsushi Murai  */
25972a1bcfSBrian Somers #include <sys/param.h>
2675240ed1SBrian Somers #include <netinet/in.h>
27eaa4df37SBrian Somers #include <netinet/in_systm.h>
28eaa4df37SBrian Somers #include <netinet/ip.h>
291fa665f5SBrian Somers #include <sys/un.h>
3075240ed1SBrian Somers 
31d5015272SBrian Somers #include <pwd.h>
3275240ed1SBrian Somers #include <stdio.h>
3375240ed1SBrian Somers #include <string.h>
34aceaed92SBrian Somers #include <termios.h>
3575240ed1SBrian Somers #include <unistd.h>
3675240ed1SBrian Somers 
375d9e6103SBrian Somers #include "layer.h"
3875240ed1SBrian Somers #include "mbuf.h"
3975240ed1SBrian Somers #include "defs.h"
40aceaed92SBrian Somers #include "log.h"
4175240ed1SBrian Somers #include "timer.h"
42af57ed9fSAtsushi Murai #include "fsm.h"
4329e275ceSBrian Somers #include "iplist.h"
4429e275ceSBrian Somers #include "throughput.h"
45eaa4df37SBrian Somers #include "slcompress.h"
465a72b6edSBrian Somers #include "lqr.h"
475a72b6edSBrian Somers #include "hdlc.h"
48af57ed9fSAtsushi Murai #include "ipcp.h"
4953c9f6c0SAtsushi Murai #include "auth.h"
5075240ed1SBrian Somers #include "systems.h"
516140ba11SBrian Somers #include "lcp.h"
523b0f8d2eSBrian Somers #include "ccp.h"
536140ba11SBrian Somers #include "link.h"
5442d4d396SBrian Somers #include "descriptor.h"
55b6dec9f0SBrian Somers #include "chat.h"
565d9e6103SBrian Somers #include "proto.h"
575ca5389aSBrian Somers #include "filter.h"
583b0f8d2eSBrian Somers #include "mp.h"
59972a1bcfSBrian Somers #ifndef NORADIUS
60972a1bcfSBrian Somers #include "radius.h"
61972a1bcfSBrian Somers #endif
62aceaed92SBrian Somers #include "cbcp.h"
63aceaed92SBrian Somers #include "chap.h"
64aceaed92SBrian Somers #include "async.h"
65aceaed92SBrian Somers #include "physical.h"
66aceaed92SBrian Somers #include "datalink.h"
675828db6dSBrian Somers #include "bundle.h"
68af57ed9fSAtsushi Murai 
69455aabc3SBrian Somers const char *
705e315498SBrian Somers Auth2Nam(u_short auth, u_char type)
71ed6a16c1SPoul-Henning Kamp {
725e315498SBrian Somers   static char chap[10];
735e315498SBrian Somers 
74455aabc3SBrian Somers   switch (auth) {
75455aabc3SBrian Somers   case PROTO_PAP:
76455aabc3SBrian Somers     return "PAP";
77455aabc3SBrian Somers   case PROTO_CHAP:
785e315498SBrian Somers     snprintf(chap, sizeof chap, "CHAP 0x%02x", type);
795e315498SBrian Somers     return chap;
80455aabc3SBrian Somers   case 0:
81455aabc3SBrian Somers     return "none";
82d025849cSBrian Somers   }
83455aabc3SBrian Somers   return "unknown";
8453c9f6c0SAtsushi Murai }
8553c9f6c0SAtsushi Murai 
86d5015272SBrian Somers static int
87d5015272SBrian Somers auth_CheckPasswd(const char *name, const char *data, const char *key)
88d5015272SBrian Somers {
89d5015272SBrian Somers   if (!strcmp(data, "*")) {
90d5015272SBrian Somers     /* Then look up the real password database */
91d5015272SBrian Somers     struct passwd *pw;
92d5015272SBrian Somers     int result;
93d5015272SBrian Somers 
94d5015272SBrian Somers     result = (pw = getpwnam(name)) &&
95d5015272SBrian Somers              !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd);
96d5015272SBrian Somers     endpwent();
97d5015272SBrian Somers     return result;
98d5015272SBrian Somers   }
99d5015272SBrian Somers 
100d5015272SBrian Somers   return !strcmp(data, key);
101d5015272SBrian Somers }
102d5015272SBrian Somers 
1031ae349f5Scvs2svn int
10492b09558SBrian Somers auth_SetPhoneList(const char *name, char *phone, int phonelen)
10592b09558SBrian Somers {
10692b09558SBrian Somers   FILE *fp;
107c39aa54eSBrian Somers   int n, lineno;
10892b09558SBrian Somers   char *vector[6];
10992b09558SBrian Somers   char buff[LINE_LEN];
11092b09558SBrian Somers 
11192b09558SBrian Somers   fp = OpenSecret(SECRETFILE);
112c39aa54eSBrian Somers   lineno = 0;
11392b09558SBrian Somers   if (fp != NULL) {
11492b09558SBrian Somers     while (fgets(buff, sizeof buff, fp)) {
115c39aa54eSBrian Somers       lineno++;
11692b09558SBrian Somers       if (buff[0] == '#')
11792b09558SBrian Somers         continue;
11892b09558SBrian Somers       buff[strlen(buff) - 1] = '\0';
11992b09558SBrian Somers       memset(vector, '\0', sizeof vector);
120c39aa54eSBrian Somers       if ((n = MakeArgs(buff, vector, VECSIZE(vector))) < 0)
121c39aa54eSBrian Somers         log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
12292b09558SBrian Somers       if (n < 5)
12392b09558SBrian Somers         continue;
12492b09558SBrian Somers       if (strcmp(vector[0], name) == 0) {
12592b09558SBrian Somers         CloseSecret(fp);
12692b09558SBrian Somers         if (*vector[4] == '\0')
12792b09558SBrian Somers           return 0;
12892b09558SBrian Somers         strncpy(phone, vector[4], phonelen - 1);
12992b09558SBrian Somers         phone[phonelen - 1] = '\0';
13092b09558SBrian Somers         return 1;		/* Valid */
13192b09558SBrian Somers       }
13292b09558SBrian Somers     }
13392b09558SBrian Somers     CloseSecret(fp);
13492b09558SBrian Somers   }
13592b09558SBrian Somers   *phone = '\0';
13692b09558SBrian Somers   return 0;
13792b09558SBrian Somers }
13892b09558SBrian Somers 
13992b09558SBrian Somers int
14092b09558SBrian Somers auth_Select(struct bundle *bundle, const char *name)
141944f7098SBrian Somers {
14253c9f6c0SAtsushi Murai   FILE *fp;
143c39aa54eSBrian Somers   int n, lineno;
1441ae349f5Scvs2svn   char *vector[5];
14586e02934SBrian Somers   char buff[LINE_LEN];
14653c9f6c0SAtsushi Murai 
147643f4904SBrian Somers   if (*name == '\0') {
148972a1bcfSBrian Somers     ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
149643f4904SBrian Somers     return 1;
150643f4904SBrian Somers   }
151643f4904SBrian Somers 
152972a1bcfSBrian Somers #ifndef NORADIUS
153972a1bcfSBrian Somers   if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE) {
154972a1bcfSBrian Somers     /* We've got a radius IP - it overrides everything */
155972a1bcfSBrian Somers     if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip))
156972a1bcfSBrian Somers       return 0;
157972a1bcfSBrian Somers     ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr);
158972a1bcfSBrian Somers     /* Continue with ppp.secret in case we've got a new label */
159972a1bcfSBrian Somers   }
160972a1bcfSBrian Somers #endif
161972a1bcfSBrian Somers 
162643f4904SBrian Somers   fp = OpenSecret(SECRETFILE);
163c39aa54eSBrian Somers   lineno = 0;
164d5015272SBrian Somers   if (fp != NULL) {
16570ee81ffSBrian Somers     while (fgets(buff, sizeof buff, fp)) {
166c39aa54eSBrian Somers       lineno++;
16753c9f6c0SAtsushi Murai       if (buff[0] == '#')
16853c9f6c0SAtsushi Murai         continue;
169501f5480SBrian Somers       buff[strlen(buff) - 1] = '\0';
17070ee81ffSBrian Somers       memset(vector, '\0', sizeof vector);
171c39aa54eSBrian Somers       if ((n = MakeArgs(buff, vector, VECSIZE(vector))) < 0)
172c39aa54eSBrian Somers         log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
1731ae349f5Scvs2svn       if (n < 2)
17453c9f6c0SAtsushi Murai         continue;
175501f5480SBrian Somers       if (strcmp(vector[0], name) == 0) {
1761ae349f5Scvs2svn         CloseSecret(fp);
177972a1bcfSBrian Somers #ifndef NORADIUS
178972a1bcfSBrian Somers         if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) {
179972a1bcfSBrian Somers #endif
18092b09558SBrian Somers           if (n > 2 && *vector[2] && strcmp(vector[2], "*") &&
18192b09558SBrian Somers               !ipcp_UseHisaddr(bundle, vector[2], 1))
182643f4904SBrian Somers             return 0;
183972a1bcfSBrian Somers           ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
184972a1bcfSBrian Somers #ifndef NORADIUS
185972a1bcfSBrian Somers         }
186972a1bcfSBrian Somers #endif
18792b09558SBrian Somers         if (n > 3 && *vector[3] && strcmp(vector[3], "*"))
18849052c95SBrian Somers           bundle_SetLabel(bundle, vector[3]);
189d5015272SBrian Somers         return 1;		/* Valid */
19053c9f6c0SAtsushi Murai       }
191501f5480SBrian Somers     }
19253c9f6c0SAtsushi Murai     CloseSecret(fp);
193643f4904SBrian Somers   }
194643f4904SBrian Somers 
195643f4904SBrian Somers #ifndef NOPASSWDAUTH
196643f4904SBrian Somers   /* Let 'em in anyway - they must have been in the passwd file */
197972a1bcfSBrian Somers   ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
198643f4904SBrian Somers   return 1;
199643f4904SBrian Somers #else
200972a1bcfSBrian Somers #ifndef NORADIUS
201972a1bcfSBrian Somers   if (bundle->radius.valid)
202972a1bcfSBrian Somers     return 1;
203972a1bcfSBrian Somers #endif
204972a1bcfSBrian Somers 
205972a1bcfSBrian Somers   /* Disappeared from ppp.secret ??? */
206643f4904SBrian Somers   return 0;
207643f4904SBrian Somers #endif
20853c9f6c0SAtsushi Murai }
20953c9f6c0SAtsushi Murai 
210af57ed9fSAtsushi Murai int
211972a1bcfSBrian Somers auth_Validate(struct bundle *bundle, const char *name,
212643f4904SBrian Somers              const char *key, struct physical *physical)
213af57ed9fSAtsushi Murai {
214643f4904SBrian Somers   /* Used by PAP routines */
215643f4904SBrian Somers 
216af57ed9fSAtsushi Murai   FILE *fp;
217c39aa54eSBrian Somers   int n, lineno;
2189c97abd8SBrian Somers   char *vector[5];
21986e02934SBrian Somers   char buff[LINE_LEN];
220af57ed9fSAtsushi Murai 
221643f4904SBrian Somers   fp = OpenSecret(SECRETFILE);
222c39aa54eSBrian Somers   lineno = 0;
223643f4904SBrian Somers   if (fp != NULL) {
22470ee81ffSBrian Somers     while (fgets(buff, sizeof buff, fp)) {
225c39aa54eSBrian Somers       lineno++;
226af57ed9fSAtsushi Murai       if (buff[0] == '#')
227af57ed9fSAtsushi Murai         continue;
228af57ed9fSAtsushi Murai       buff[strlen(buff) - 1] = 0;
22970ee81ffSBrian Somers       memset(vector, '\0', sizeof vector);
230c39aa54eSBrian Somers       if ((n = MakeArgs(buff, vector, VECSIZE(vector))) < 0)
231c39aa54eSBrian Somers         log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
232af57ed9fSAtsushi Murai       if (n < 2)
233af57ed9fSAtsushi Murai         continue;
234972a1bcfSBrian Somers       if (strcmp(vector[0], name) == 0) {
235af57ed9fSAtsushi Murai         CloseSecret(fp);
236972a1bcfSBrian Somers         return auth_CheckPasswd(name, vector[1], key);
237af57ed9fSAtsushi Murai       }
238af57ed9fSAtsushi Murai     }
239af57ed9fSAtsushi Murai     CloseSecret(fp);
240d5015272SBrian Somers   }
241d5015272SBrian Somers 
242d5015272SBrian Somers #ifndef NOPASSWDAUTH
2431342caedSBrian Somers   if (Enabled(bundle, OPT_PASSWDAUTH))
244972a1bcfSBrian Somers     return auth_CheckPasswd(name, "*", key);
245d5015272SBrian Somers #endif
246d5015272SBrian Somers 
247d5015272SBrian Somers   return 0;			/* Invalid */
248af57ed9fSAtsushi Murai }
249af57ed9fSAtsushi Murai 
250af57ed9fSAtsushi Murai char *
251972a1bcfSBrian Somers auth_GetSecret(struct bundle *bundle, const char *name, int len,
252643f4904SBrian Somers               struct physical *physical)
253af57ed9fSAtsushi Murai {
254d5015272SBrian Somers   /* Used by CHAP routines */
255d5015272SBrian Somers 
256af57ed9fSAtsushi Murai   FILE *fp;
257c39aa54eSBrian Somers   int n, lineno;
2589c97abd8SBrian Somers   char *vector[5];
259c506ecd5SBrian Somers   static char buff[LINE_LEN];	/* vector[] will point here when returned */
260af57ed9fSAtsushi Murai 
261643f4904SBrian Somers   fp = OpenSecret(SECRETFILE);
262af57ed9fSAtsushi Murai   if (fp == NULL)
263af57ed9fSAtsushi Murai     return (NULL);
264d5015272SBrian Somers 
265c39aa54eSBrian Somers   lineno = 0;
26670ee81ffSBrian Somers   while (fgets(buff, sizeof buff, fp)) {
267c39aa54eSBrian Somers     lineno++;
268af57ed9fSAtsushi Murai     if (buff[0] == '#')
269af57ed9fSAtsushi Murai       continue;
270c506ecd5SBrian Somers     n = strlen(buff) - 1;
271c506ecd5SBrian Somers     if (buff[n] == '\n')
272c506ecd5SBrian Somers       buff[n] = '\0';	/* Trim the '\n' */
27370ee81ffSBrian Somers     memset(vector, '\0', sizeof vector);
274c39aa54eSBrian Somers     if ((n = MakeArgs(buff, vector, VECSIZE(vector))) < 0)
275c39aa54eSBrian Somers       log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
276af57ed9fSAtsushi Murai     if (n < 2)
277af57ed9fSAtsushi Murai       continue;
278972a1bcfSBrian Somers     if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) {
279643f4904SBrian Somers       CloseSecret(fp);
280d5015272SBrian Somers       return vector[1];
281af57ed9fSAtsushi Murai     }
282af57ed9fSAtsushi Murai   }
283af57ed9fSAtsushi Murai   CloseSecret(fp);
284af57ed9fSAtsushi Murai   return (NULL);		/* Invalid */
285af57ed9fSAtsushi Murai }
28653c9f6c0SAtsushi Murai 
28753c9f6c0SAtsushi Murai static void
288b6e82f33SBrian Somers AuthTimeout(void *vauthp)
28953c9f6c0SAtsushi Murai {
290b6e82f33SBrian Somers   struct authinfo *authp = (struct authinfo *)vauthp;
29153c9f6c0SAtsushi Murai 
292dd7e2610SBrian Somers   timer_Stop(&authp->authtimer);
29353c9f6c0SAtsushi Murai   if (--authp->retry > 0) {
294f0cdd9c0SBrian Somers     authp->id++;
295f0cdd9c0SBrian Somers     (*authp->fn.req)(authp);
296dd7e2610SBrian Somers     timer_Start(&authp->authtimer);
297aceaed92SBrian Somers   } else {
298aceaed92SBrian Somers     log_Printf(LogPHASE, "Auth: No response from server\n");
299aceaed92SBrian Somers     datalink_AuthNotOk(authp->physical->dl);
300aceaed92SBrian Somers   }
30153c9f6c0SAtsushi Murai }
30253c9f6c0SAtsushi Murai 
30353c9f6c0SAtsushi Murai void
304f0cdd9c0SBrian Somers auth_Init(struct authinfo *authp, struct physical *p, auth_func req,
305f0cdd9c0SBrian Somers           auth_func success, auth_func failure)
30653c9f6c0SAtsushi Murai {
307f0cdd9c0SBrian Somers   memset(authp, '\0', sizeof(struct authinfo));
308479508cfSBrian Somers   authp->cfg.fsm.timeout = DEF_FSMRETRY;
309479508cfSBrian Somers   authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES;
310479508cfSBrian Somers   authp->cfg.fsm.maxtrm = 0;	/* not used */
311f0cdd9c0SBrian Somers   authp->fn.req = req;
312f0cdd9c0SBrian Somers   authp->fn.success = success;
313f0cdd9c0SBrian Somers   authp->fn.failure = failure;
314f0cdd9c0SBrian Somers   authp->physical = p;
315e2ebb036SBrian Somers }
31653c9f6c0SAtsushi Murai 
317e2ebb036SBrian Somers void
318f0cdd9c0SBrian Somers auth_StartReq(struct authinfo *authp)
319e2ebb036SBrian Somers {
320dd7e2610SBrian Somers   timer_Stop(&authp->authtimer);
321e2ebb036SBrian Somers   authp->authtimer.func = AuthTimeout;
3223b0f8d2eSBrian Somers   authp->authtimer.name = "auth";
323479508cfSBrian Somers   authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS;
324e2ebb036SBrian Somers   authp->authtimer.arg = (void *)authp;
325479508cfSBrian Somers   authp->retry = authp->cfg.fsm.maxreq;
32653c9f6c0SAtsushi Murai   authp->id = 1;
327f0cdd9c0SBrian Somers   (*authp->fn.req)(authp);
328dd7e2610SBrian Somers   timer_Start(&authp->authtimer);
32953c9f6c0SAtsushi Murai }
33053c9f6c0SAtsushi Murai 
33153c9f6c0SAtsushi Murai void
332dd7e2610SBrian Somers auth_StopTimer(struct authinfo *authp)
33353c9f6c0SAtsushi Murai {
334dd7e2610SBrian Somers   timer_Stop(&authp->authtimer);
335f0cdd9c0SBrian Somers }
336f0cdd9c0SBrian Somers 
337f0cdd9c0SBrian Somers struct mbuf *
338f0cdd9c0SBrian Somers auth_ReadHeader(struct authinfo *authp, struct mbuf *bp)
339f0cdd9c0SBrian Somers {
340f0cdd9c0SBrian Somers   int len;
341f0cdd9c0SBrian Somers 
34226af0ae9SBrian Somers   len = m_length(bp);
343f0cdd9c0SBrian Somers   if (len >= sizeof authp->in.hdr) {
344f0cdd9c0SBrian Somers     bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr);
345f0cdd9c0SBrian Somers     if (len >= ntohs(authp->in.hdr.length))
346f0cdd9c0SBrian Somers       return bp;
347b7ff18adSBrian Somers     authp->in.hdr.length = htons(0);
348b31a24caSBrian Somers     log_Printf(LogWARN, "auth_ReadHeader: Short packet (%d > %d) !\n",
349b31a24caSBrian Somers                ntohs(authp->in.hdr.length), len);
350b7ff18adSBrian Somers   } else {
351b7ff18adSBrian Somers     authp->in.hdr.length = htons(0);
352b31a24caSBrian Somers     log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%d > %d) !\n",
353eb2d27cfSBrian Somers                (int)(sizeof authp->in.hdr), len);
354b7ff18adSBrian Somers   }
355f0cdd9c0SBrian Somers 
35626af0ae9SBrian Somers   m_freem(bp);
357f0cdd9c0SBrian Somers   return NULL;
358f0cdd9c0SBrian Somers }
359f0cdd9c0SBrian Somers 
360f0cdd9c0SBrian Somers struct mbuf *
361f0cdd9c0SBrian Somers auth_ReadName(struct authinfo *authp, struct mbuf *bp, int len)
362f0cdd9c0SBrian Somers {
363f0cdd9c0SBrian Somers   if (len > sizeof authp->in.name - 1)
364b31a24caSBrian Somers     log_Printf(LogWARN, "auth_ReadName: Name too long (%d) !\n", len);
365f0cdd9c0SBrian Somers   else {
36626af0ae9SBrian Somers     int mlen = m_length(bp);
367f0cdd9c0SBrian Somers 
368f0cdd9c0SBrian Somers     if (len > mlen)
369b31a24caSBrian Somers       log_Printf(LogWARN, "auth_ReadName: Short packet (%d > %d) !\n",
370b31a24caSBrian Somers                  len, mlen);
371f0cdd9c0SBrian Somers     else {
372f0cdd9c0SBrian Somers       bp = mbuf_Read(bp, (u_char *)authp->in.name, len);
373f0cdd9c0SBrian Somers       authp->in.name[len] = '\0';
374f0cdd9c0SBrian Somers       return bp;
375f0cdd9c0SBrian Somers     }
376f0cdd9c0SBrian Somers   }
377f0cdd9c0SBrian Somers 
378f0cdd9c0SBrian Somers   *authp->in.name = '\0';
37926af0ae9SBrian Somers   m_freem(bp);
380f0cdd9c0SBrian Somers   return NULL;
38153c9f6c0SAtsushi Murai }
382