xref: /freebsd/usr.sbin/ppp/auth.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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