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)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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>
52 #include "throughput.h"
53 #include "slcompress.h"
63 #include "descriptor.h"
81 Auth2Nam(u_short auth, u_char type)
89 snprintf(chap, sizeof chap, "CHAP 0x%02x", type);
98 auth_CheckPasswd(const char *name, const char *data, const char *key)
100 if (!strcmp(data, "*")) {
101 /* Then look up the real password database */
105 result = (pw = getpwnam(name)) &&
106 !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd);
111 return !strcmp(data, key);
115 auth_SetPhoneList(const char *name, char *phone, int phonelen)
119 char *vector[6], buff[LINE_LEN];
122 fp = OpenSecret(SECRETFILE);
126 while (fgets(buff, sizeof buff, fp)) {
130 buff[strlen(buff) - 1] = '\0';
131 memset(vector, '\0', sizeof vector);
132 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
133 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
136 if (strcmp(vector[0], name) == 0) {
138 if (*vector[4] == '\0')
140 strncpy(phone, vector[4], phonelen - 1);
141 phone[phonelen - 1] = '\0';
142 return 1; /* Valid */
146 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
147 /* Look for the name without the leading domain */
160 auth_Select(struct bundle *bundle, const char *name)
164 char *vector[5], buff[LINE_LEN];
168 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
173 if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE &&
174 bundle->radius.ip.s_addr != RADIUS_INADDR_POOL) {
175 /* We've got a radius IP - it overrides everything */
176 if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip))
178 ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr);
179 /* Continue with ppp.secret in case we've got a new label */
183 fp = OpenSecret(SECRETFILE);
187 while (fgets(buff, sizeof buff, fp)) {
191 buff[strlen(buff) - 1] = '\0';
192 memset(vector, '\0', sizeof vector);
193 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
194 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
197 if (strcmp(vector[0], name) == 0) {
200 if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) {
202 if (n > 2 && *vector[2] && strcmp(vector[2], "*") &&
203 !ipcp_UseHisaddr(bundle, vector[2], 1))
205 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
209 if (n > 3 && *vector[3] && strcmp(vector[3], "*"))
210 bundle_SetLabel(bundle, vector[3]);
211 return 1; /* Valid */
215 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
216 /* Look for the name without the leading domain */
226 /* Let 'em in anyway - they must have been in the passwd file */
227 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
231 if (bundle->radius.valid)
235 /* Disappeared from ppp.secret ??? */
241 auth_Validate(struct bundle *bundle, const char *name,
242 const char *key, struct physical *physical)
244 /* Used by PAP routines */
248 char *vector[5], buff[LINE_LEN];
251 fp = OpenSecret(SECRETFILE);
255 while (fgets(buff, sizeof buff, fp)) {
259 buff[strlen(buff) - 1] = 0;
260 memset(vector, '\0', sizeof vector);
261 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
262 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
265 if (strcmp(vector[0], name) == 0) {
267 return auth_CheckPasswd(name, vector[1], key);
272 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
273 /* Look for the name without the leading domain */
285 if (Enabled(bundle, OPT_PASSWDAUTH))
286 return auth_CheckPasswd(name, "*", key);
289 return 0; /* Invalid */
293 auth_GetSecret(struct bundle *bundle, const char *name, int len,
294 struct physical *physical)
296 /* Used by CHAP routines */
302 static char buff[LINE_LEN]; /* vector[] will point here when returned */
304 fp = OpenSecret(SECRETFILE);
310 while (fgets(buff, sizeof buff, fp)) {
314 n = strlen(buff) - 1;
316 buff[n] = '\0'; /* Trim the '\n' */
317 memset(vector, '\0', sizeof vector);
318 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
319 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
322 if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) {
328 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
329 /* Go back and look for the name without the leading domain */
330 len -= slash - name + 1;
337 return (NULL); /* Invalid */
341 AuthTimeout(void *vauthp)
343 struct authinfo *authp = (struct authinfo *)vauthp;
345 timer_Stop(&authp->authtimer);
346 if (--authp->retry > 0) {
348 (*authp->fn.req)(authp);
349 timer_Start(&authp->authtimer);
351 log_Printf(LogPHASE, "Auth: No response from server\n");
352 datalink_AuthNotOk(authp->physical->dl);
357 auth_Init(struct authinfo *authp, struct physical *p, auth_func req,
358 auth_func success, auth_func failure)
360 memset(authp, '\0', sizeof(struct authinfo));
361 authp->cfg.fsm.timeout = DEF_FSMRETRY;
362 authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES;
363 authp->cfg.fsm.maxtrm = 0; /* not used */
365 authp->fn.success = success;
366 authp->fn.failure = failure;
371 auth_StartReq(struct authinfo *authp)
373 timer_Stop(&authp->authtimer);
374 authp->authtimer.func = AuthTimeout;
375 authp->authtimer.name = "auth";
376 authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS;
377 authp->authtimer.arg = (void *)authp;
378 authp->retry = authp->cfg.fsm.maxreq;
380 (*authp->fn.req)(authp);
381 timer_Start(&authp->authtimer);
385 auth_StopTimer(struct authinfo *authp)
387 timer_Stop(&authp->authtimer);
391 auth_ReadHeader(struct authinfo *authp, struct mbuf *bp)
396 if (len >= sizeof authp->in.hdr) {
397 bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr);
398 if (len >= ntohs(authp->in.hdr.length))
400 authp->in.hdr.length = htons(0);
401 log_Printf(LogWARN, "auth_ReadHeader: Short packet (%d > %d) !\n",
402 ntohs(authp->in.hdr.length), len);
404 authp->in.hdr.length = htons(0);
405 log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%d > %d) !\n",
406 (int)(sizeof authp->in.hdr), len);
414 auth_ReadName(struct authinfo *authp, struct mbuf *bp, int len)
416 if (len > sizeof authp->in.name - 1)
417 log_Printf(LogWARN, "auth_ReadName: Name too long (%d) !\n", len);
419 int mlen = m_length(bp);
422 log_Printf(LogWARN, "auth_ReadName: Short packet (%d > %d) !\n",
425 bp = mbuf_Read(bp, (u_char *)authp->in.name, len);
426 authp->in.name[len] = '\0';
431 *authp->in.name = '\0';