xref: /freebsd/usr.sbin/ppp/auth.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
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;
108   char *vector[6];
109   char buff[LINE_LEN];
110 
111   fp = OpenSecret(SECRETFILE);
112   if (fp != NULL) {
113     while (fgets(buff, sizeof buff, fp)) {
114       if (buff[0] == '#')
115         continue;
116       buff[strlen(buff) - 1] = '\0';
117       memset(vector, '\0', sizeof vector);
118       n = MakeArgs(buff, vector, VECSIZE(vector));
119       if (n < 5)
120         continue;
121       if (strcmp(vector[0], name) == 0) {
122         CloseSecret(fp);
123         if (*vector[4] == '\0')
124           return 0;
125         strncpy(phone, vector[4], phonelen - 1);
126         phone[phonelen - 1] = '\0';
127         return 1;		/* Valid */
128       }
129     }
130     CloseSecret(fp);
131   }
132   *phone = '\0';
133   return 0;
134 }
135 
136 int
137 auth_Select(struct bundle *bundle, const char *name)
138 {
139   FILE *fp;
140   int n;
141   char *vector[5];
142   char buff[LINE_LEN];
143 
144   if (*name == '\0') {
145     ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
146     return 1;
147   }
148 
149 #ifndef NORADIUS
150   if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE) {
151     /* We've got a radius IP - it overrides everything */
152     if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip))
153       return 0;
154     ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr);
155     /* Continue with ppp.secret in case we've got a new label */
156   }
157 #endif
158 
159   fp = OpenSecret(SECRETFILE);
160   if (fp != NULL) {
161     while (fgets(buff, sizeof buff, fp)) {
162       if (buff[0] == '#')
163         continue;
164       buff[strlen(buff) - 1] = '\0';
165       memset(vector, '\0', sizeof vector);
166       n = MakeArgs(buff, vector, VECSIZE(vector));
167       if (n < 2)
168         continue;
169       if (strcmp(vector[0], name) == 0) {
170         CloseSecret(fp);
171 #ifndef NORADIUS
172         if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) {
173 #endif
174           if (n > 2 && *vector[2] && strcmp(vector[2], "*") &&
175               !ipcp_UseHisaddr(bundle, vector[2], 1))
176             return 0;
177           ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
178 #ifndef NORADIUS
179         }
180 #endif
181         if (n > 3 && *vector[3] && strcmp(vector[3], "*"))
182           bundle_SetLabel(bundle, vector[3]);
183         return 1;		/* Valid */
184       }
185     }
186     CloseSecret(fp);
187   }
188 
189 #ifndef NOPASSWDAUTH
190   /* Let 'em in anyway - they must have been in the passwd file */
191   ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
192   return 1;
193 #else
194 #ifndef NORADIUS
195   if (bundle->radius.valid)
196     return 1;
197 #endif
198 
199   /* Disappeared from ppp.secret ??? */
200   return 0;
201 #endif
202 }
203 
204 int
205 auth_Validate(struct bundle *bundle, const char *name,
206              const char *key, struct physical *physical)
207 {
208   /* Used by PAP routines */
209 
210   FILE *fp;
211   int n;
212   char *vector[5];
213   char buff[LINE_LEN];
214 
215   fp = OpenSecret(SECRETFILE);
216   if (fp != NULL) {
217     while (fgets(buff, sizeof buff, fp)) {
218       if (buff[0] == '#')
219         continue;
220       buff[strlen(buff) - 1] = 0;
221       memset(vector, '\0', sizeof vector);
222       n = MakeArgs(buff, vector, VECSIZE(vector));
223       if (n < 2)
224         continue;
225       if (strcmp(vector[0], name) == 0) {
226         CloseSecret(fp);
227         return auth_CheckPasswd(name, vector[1], key);
228       }
229     }
230     CloseSecret(fp);
231   }
232 
233 #ifndef NOPASSWDAUTH
234   if (Enabled(bundle, OPT_PASSWDAUTH))
235     return auth_CheckPasswd(name, "*", key);
236 #endif
237 
238   return 0;			/* Invalid */
239 }
240 
241 char *
242 auth_GetSecret(struct bundle *bundle, const char *name, int len,
243               struct physical *physical)
244 {
245   /* Used by CHAP routines */
246 
247   FILE *fp;
248   int n;
249   char *vector[5];
250   static char buff[LINE_LEN];	/* vector[] will point here when returned */
251 
252   fp = OpenSecret(SECRETFILE);
253   if (fp == NULL)
254     return (NULL);
255 
256   while (fgets(buff, sizeof buff, fp)) {
257     if (buff[0] == '#')
258       continue;
259     n = strlen(buff) - 1;
260     if (buff[n] == '\n')
261       buff[n] = '\0';	/* Trim the '\n' */
262     memset(vector, '\0', sizeof vector);
263     n = MakeArgs(buff, vector, VECSIZE(vector));
264     if (n < 2)
265       continue;
266     if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) {
267       CloseSecret(fp);
268       return vector[1];
269     }
270   }
271   CloseSecret(fp);
272   return (NULL);		/* Invalid */
273 }
274 
275 static void
276 AuthTimeout(void *vauthp)
277 {
278   struct authinfo *authp = (struct authinfo *)vauthp;
279 
280   timer_Stop(&authp->authtimer);
281   if (--authp->retry > 0) {
282     authp->id++;
283     (*authp->fn.req)(authp);
284     timer_Start(&authp->authtimer);
285   } else {
286     log_Printf(LogPHASE, "Auth: No response from server\n");
287     datalink_AuthNotOk(authp->physical->dl);
288   }
289 }
290 
291 void
292 auth_Init(struct authinfo *authp, struct physical *p, auth_func req,
293           auth_func success, auth_func failure)
294 {
295   memset(authp, '\0', sizeof(struct authinfo));
296   authp->cfg.fsm.timeout = DEF_FSMRETRY;
297   authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES;
298   authp->cfg.fsm.maxtrm = 0;	/* not used */
299   authp->fn.req = req;
300   authp->fn.success = success;
301   authp->fn.failure = failure;
302   authp->physical = p;
303 }
304 
305 void
306 auth_StartReq(struct authinfo *authp)
307 {
308   timer_Stop(&authp->authtimer);
309   authp->authtimer.func = AuthTimeout;
310   authp->authtimer.name = "auth";
311   authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS;
312   authp->authtimer.arg = (void *)authp;
313   authp->retry = authp->cfg.fsm.maxreq;
314   authp->id = 1;
315   (*authp->fn.req)(authp);
316   timer_Start(&authp->authtimer);
317 }
318 
319 void
320 auth_StopTimer(struct authinfo *authp)
321 {
322   timer_Stop(&authp->authtimer);
323 }
324 
325 struct mbuf *
326 auth_ReadHeader(struct authinfo *authp, struct mbuf *bp)
327 {
328   int len;
329 
330   len = mbuf_Length(bp);
331   if (len >= sizeof authp->in.hdr) {
332     bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr);
333     if (len >= ntohs(authp->in.hdr.length))
334       return bp;
335     authp->in.hdr.length = htons(0);
336     log_Printf(LogWARN, "auth_ReadHeader: Short packet (%d > %d) !\n",
337                ntohs(authp->in.hdr.length), len);
338   } else {
339     authp->in.hdr.length = htons(0);
340     log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%d > %d) !\n",
341                (int)(sizeof authp->in.hdr), len);
342   }
343 
344   mbuf_Free(bp);
345   return NULL;
346 }
347 
348 struct mbuf *
349 auth_ReadName(struct authinfo *authp, struct mbuf *bp, int len)
350 {
351   if (len > sizeof authp->in.name - 1)
352     log_Printf(LogWARN, "auth_ReadName: Name too long (%d) !\n", len);
353   else {
354     int mlen = mbuf_Length(bp);
355 
356     if (len > mlen)
357       log_Printf(LogWARN, "auth_ReadName: Short packet (%d > %d) !\n",
358                  len, mlen);
359     else {
360       bp = mbuf_Read(bp, (u_char *)authp->in.name, len);
361       authp->in.name[len] = '\0';
362       return bp;
363     }
364   }
365 
366   *authp->in.name = '\0';
367   mbuf_Free(bp);
368   return NULL;
369 }
370