dhcpcd: update README.DRAGONFLY
[dragonfly.git] / usr.sbin / ppp / auth.c
blob7aa4c9e9837ceb892933f7a70c094255bd9bc361
1 /*-
2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
28 * $FreeBSD: src/usr.sbin/ppp/auth.c,v 1.50.2.2 2002/09/01 02:12:22 brian Exp $
29 * $DragonFly: src/usr.sbin/ppp/auth.c,v 1.2 2003/06/17 04:30:00 dillon Exp $
32 #include <sys/param.h>
33 #include <netinet/in.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36 #include <sys/socket.h>
37 #include <sys/un.h>
39 #include <pwd.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <termios.h>
43 #include <unistd.h>
45 #include "layer.h"
46 #include "mbuf.h"
47 #include "defs.h"
48 #include "log.h"
49 #include "timer.h"
50 #include "fsm.h"
51 #include "iplist.h"
52 #include "throughput.h"
53 #include "slcompress.h"
54 #include "lqr.h"
55 #include "hdlc.h"
56 #include "ncpaddr.h"
57 #include "ipcp.h"
58 #include "auth.h"
59 #include "systems.h"
60 #include "lcp.h"
61 #include "ccp.h"
62 #include "link.h"
63 #include "descriptor.h"
64 #include "chat.h"
65 #include "proto.h"
66 #include "filter.h"
67 #include "mp.h"
68 #ifndef NORADIUS
69 #include "radius.h"
70 #endif
71 #include "cbcp.h"
72 #include "chap.h"
73 #include "async.h"
74 #include "physical.h"
75 #include "datalink.h"
76 #include "ipv6cp.h"
77 #include "ncp.h"
78 #include "bundle.h"
80 const char *
81 Auth2Nam(u_short auth, u_char type)
83 static char chap[10];
85 switch (auth) {
86 case PROTO_PAP:
87 return "PAP";
88 case PROTO_CHAP:
89 snprintf(chap, sizeof chap, "CHAP 0x%02x", type);
90 return chap;
91 case 0:
92 return "none";
94 return "unknown";
97 static int
98 auth_CheckPasswd(const char *name, const char *data, const char *key)
100 struct passwd *pw;
101 int result = 0;
102 char *cryptpw;
104 if (!strcmp(data, "*")) {
105 /* Then look up the real password database */
106 pw = getpwnam(name);
108 if (pw) {
109 cryptpw = crypt(key, pw->pw_passwd);
111 result = (cryptpw != NULL) && !strcmp(cryptpw, pw->pw_passwd);
114 endpwent();
116 return result;
119 return !strcmp(data, key);
123 auth_SetPhoneList(const char *name, char *phone, int phonelen)
125 FILE *fp;
126 int n, lineno;
127 char *vector[6], buff[LINE_LEN];
128 const char *slash;
130 fp = OpenSecret(SECRETFILE);
131 if (fp != NULL) {
132 again:
133 lineno = 0;
134 while (fgets(buff, sizeof buff, fp)) {
135 lineno++;
136 if (buff[0] == '#')
137 continue;
138 buff[strlen(buff) - 1] = '\0';
139 memset(vector, '\0', sizeof vector);
140 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
141 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
142 if (n < 5)
143 continue;
144 if (strcmp(vector[0], name) == 0) {
145 CloseSecret(fp);
146 if (*vector[4] == '\0')
147 return 0;
148 strncpy(phone, vector[4], phonelen - 1);
149 phone[phonelen - 1] = '\0';
150 return 1; /* Valid */
154 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
155 /* Look for the name without the leading domain */
156 name = slash + 1;
157 rewind(fp);
158 goto again;
161 CloseSecret(fp);
163 *phone = '\0';
164 return 0;
168 auth_Select(struct bundle *bundle, const char *name)
170 FILE *fp;
171 int n, lineno;
172 char *vector[5], buff[LINE_LEN];
173 const char *slash;
175 if (*name == '\0') {
176 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
177 return 1;
180 #ifndef NORADIUS
181 if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE &&
182 bundle->radius.ip.s_addr != RADIUS_INADDR_POOL) {
183 /* We've got a radius IP - it overrides everything */
184 if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip))
185 return 0;
186 ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr);
187 /* Continue with ppp.secret in case we've got a new label */
189 #endif
191 fp = OpenSecret(SECRETFILE);
192 if (fp != NULL) {
193 again:
194 lineno = 0;
195 while (fgets(buff, sizeof buff, fp)) {
196 lineno++;
197 if (buff[0] == '#')
198 continue;
199 buff[strlen(buff) - 1] = '\0';
200 memset(vector, '\0', sizeof vector);
201 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
202 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
203 if (n < 2)
204 continue;
205 if (strcmp(vector[0], name) == 0) {
206 CloseSecret(fp);
207 #ifndef NORADIUS
208 if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) {
209 #endif
210 if (n > 2 && *vector[2] && strcmp(vector[2], "*") &&
211 !ipcp_UseHisaddr(bundle, vector[2], 1))
212 return 0;
213 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
214 #ifndef NORADIUS
216 #endif
217 if (n > 3 && *vector[3] && strcmp(vector[3], "*"))
218 bundle_SetLabel(bundle, vector[3]);
219 return 1; /* Valid */
223 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
224 /* Look for the name without the leading domain */
225 name = slash + 1;
226 rewind(fp);
227 goto again;
230 CloseSecret(fp);
233 #ifndef NOPASSWDAUTH
234 /* Let 'em in anyway - they must have been in the passwd file */
235 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
236 return 1;
237 #else
238 #ifndef NORADIUS
239 if (bundle->radius.valid)
240 return 1;
241 #endif
243 /* Disappeared from ppp.secret ??? */
244 return 0;
245 #endif
249 auth_Validate(struct bundle *bundle, const char *name, const char *key)
251 /* Used by PAP routines */
253 FILE *fp;
254 int n, lineno;
255 char *vector[5], buff[LINE_LEN];
256 const char *slash;
258 fp = OpenSecret(SECRETFILE);
259 again:
260 lineno = 0;
261 if (fp != NULL) {
262 while (fgets(buff, sizeof buff, fp)) {
263 lineno++;
264 if (buff[0] == '#')
265 continue;
266 buff[strlen(buff) - 1] = 0;
267 memset(vector, '\0', sizeof vector);
268 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
269 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
270 if (n < 2)
271 continue;
272 if (strcmp(vector[0], name) == 0) {
273 CloseSecret(fp);
274 return auth_CheckPasswd(name, vector[1], key);
279 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
280 /* Look for the name without the leading domain */
281 name = slash + 1;
282 if (fp != NULL) {
283 rewind(fp);
284 goto again;
288 if (fp != NULL)
289 CloseSecret(fp);
291 #ifndef NOPASSWDAUTH
292 if (Enabled(bundle, OPT_PASSWDAUTH))
293 return auth_CheckPasswd(name, "*", key);
294 #endif
296 return 0; /* Invalid */
299 char *
300 auth_GetSecret(const char *name, size_t len)
302 /* Used by CHAP routines */
304 FILE *fp;
305 int n, lineno;
306 char *vector[5];
307 const char *slash;
308 static char buff[LINE_LEN]; /* vector[] will point here when returned */
310 fp = OpenSecret(SECRETFILE);
311 if (fp == NULL)
312 return (NULL);
314 again:
315 lineno = 0;
316 while (fgets(buff, sizeof buff, fp)) {
317 lineno++;
318 if (buff[0] == '#')
319 continue;
320 n = strlen(buff) - 1;
321 if (buff[n] == '\n')
322 buff[n] = '\0'; /* Trim the '\n' */
323 memset(vector, '\0', sizeof vector);
324 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
325 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
326 if (n < 2)
327 continue;
328 if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) {
329 CloseSecret(fp);
330 return vector[1];
334 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
335 /* Go back and look for the name without the leading domain */
336 len -= slash - name + 1;
337 name = slash + 1;
338 rewind(fp);
339 goto again;
342 CloseSecret(fp);
343 return (NULL); /* Invalid */
346 static void
347 AuthTimeout(void *vauthp)
349 struct authinfo *authp = (struct authinfo *)vauthp;
351 timer_Stop(&authp->authtimer);
352 if (--authp->retry > 0) {
353 authp->id++;
354 (*authp->fn.req)(authp);
355 timer_Start(&authp->authtimer);
356 } else {
357 log_Printf(LogPHASE, "Auth: No response from server\n");
358 datalink_AuthNotOk(authp->physical->dl);
362 void
363 auth_Init(struct authinfo *authp, struct physical *p, auth_func req,
364 auth_func success, auth_func failure)
366 memset(authp, '\0', sizeof(struct authinfo));
367 authp->cfg.fsm.timeout = DEF_FSMRETRY;
368 authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES;
369 authp->cfg.fsm.maxtrm = 0; /* not used */
370 authp->fn.req = req;
371 authp->fn.success = success;
372 authp->fn.failure = failure;
373 authp->physical = p;
376 void
377 auth_StartReq(struct authinfo *authp)
379 timer_Stop(&authp->authtimer);
380 authp->authtimer.func = AuthTimeout;
381 authp->authtimer.name = "auth";
382 authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS;
383 authp->authtimer.arg = (void *)authp;
384 authp->retry = authp->cfg.fsm.maxreq;
385 authp->id = 1;
386 (*authp->fn.req)(authp);
387 timer_Start(&authp->authtimer);
390 void
391 auth_StopTimer(struct authinfo *authp)
393 timer_Stop(&authp->authtimer);
396 struct mbuf *
397 auth_ReadHeader(struct authinfo *authp, struct mbuf *bp)
399 size_t len;
401 len = m_length(bp);
402 if (len >= sizeof authp->in.hdr) {
403 bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr);
404 if (len >= ntohs(authp->in.hdr.length))
405 return bp;
406 authp->in.hdr.length = htons(0);
407 log_Printf(LogWARN, "auth_ReadHeader: Short packet (%u > %zu) !\n",
408 ntohs(authp->in.hdr.length), len);
409 } else {
410 authp->in.hdr.length = htons(0);
411 log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%u > %zu) !\n",
412 (int)(sizeof authp->in.hdr), len);
415 m_freem(bp);
416 return NULL;
419 struct mbuf *
420 auth_ReadName(struct authinfo *authp, struct mbuf *bp, size_t len)
422 if (len > sizeof authp->in.name - 1)
423 log_Printf(LogWARN, "auth_ReadName: Name too long (%zu) !\n", len);
424 else {
425 size_t mlen = m_length(bp);
427 if (len > mlen)
428 log_Printf(LogWARN, "auth_ReadName: Short packet (%zu > %zu) !\n",
429 len, mlen);
430 else {
431 bp = mbuf_Read(bp, (u_char *)authp->in.name, len);
432 authp->in.name[len] = '\0';
433 return bp;
437 *authp->in.name = '\0';
438 m_freem(bp);
439 return NULL;