2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
5 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
6 * Internet Initiative Japan, Inc (IIJ)
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/param.h>
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/ip.h>
37 #include <sys/socket.h>
48 #include <security/pam_appl.h>
50 #include <security/openpam.h>
61 #include "throughput.h"
62 #include "slcompress.h"
72 #include "descriptor.h"
90 Auth2Nam(u_short auth, u_char type)
98 snprintf(chap, sizeof chap, "CHAP 0x%02x", type);
106 #if !defined(NOPAM) && !defined(OPENPAM)
108 pam_conv(int n, const struct pam_message **msg, struct pam_response **resp,
112 if (n != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
113 return (PAM_CONV_ERR);
114 if ((*resp = malloc(sizeof(struct pam_response))) == NULL)
115 return (PAM_CONV_ERR);
116 (*resp)[0].resp = strdup((const char *)data);
117 (*resp)[0].resp_retcode = 0;
119 return ((*resp)[0].resp != NULL ? PAM_SUCCESS : PAM_CONV_ERR);
121 #endif /* !defined(NOPAM) && !defined(OPENPAM) */
124 auth_CheckPasswd(const char *name, const char *data, const char *key)
126 if (!strcmp(data, "*")) {
128 /* Then look up the real password database */
133 cryptpw = crypt(key, pw->pw_passwd);
134 result = (pw = getpwnam(name)) &&
135 (cryptpw == NULL || !strcmp(cryptpw, pw->pw_passwd));
139 /* Then consult with PAM. */
143 struct pam_conv pamc = {
145 &openpam_nullconv, NULL
151 if (pam_start("ppp", name, &pamc, &pamh) != PAM_SUCCESS)
154 if ((status = pam_set_item(pamh, PAM_AUTHTOK, key)) == PAM_SUCCESS)
156 status = pam_authenticate(pamh, 0);
157 pam_end(pamh, status);
158 return (status == PAM_SUCCESS);
162 return !strcmp(data, key);
166 auth_SetPhoneList(const char *name, char *phone, int phonelen)
170 char *vector[6], buff[LINE_LEN];
173 fp = OpenSecret(SECRETFILE);
177 while (fgets(buff, sizeof buff, fp)) {
181 buff[strlen(buff) - 1] = '\0';
182 memset(vector, '\0', sizeof vector);
183 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
184 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
187 if (strcmp(vector[0], name) == 0) {
189 if (*vector[4] == '\0')
191 strncpy(phone, vector[4], phonelen - 1);
192 phone[phonelen - 1] = '\0';
193 return 1; /* Valid */
197 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
198 /* Look for the name without the leading domain */
211 auth_Select(struct bundle *bundle, const char *name)
215 char *vector[5], buff[LINE_LEN];
219 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
224 if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE &&
225 bundle->radius.ip.s_addr != RADIUS_INADDR_POOL) {
226 /* We've got a radius IP - it overrides everything */
227 if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip))
229 ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr);
230 /* Continue with ppp.secret in case we've got a new label */
234 fp = OpenSecret(SECRETFILE);
238 while (fgets(buff, sizeof buff, fp)) {
242 buff[strlen(buff) - 1] = '\0';
243 memset(vector, '\0', sizeof vector);
244 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
245 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
248 if (strcmp(vector[0], name) == 0) {
251 if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) {
253 if (n > 2 && *vector[2] && strcmp(vector[2], "*") &&
254 !ipcp_UseHisaddr(bundle, vector[2], 1))
256 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
260 if (n > 3 && *vector[3] && strcmp(vector[3], "*"))
261 bundle_SetLabel(bundle, vector[3]);
262 return 1; /* Valid */
266 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
267 /* Look for the name without the leading domain */
277 /* Let 'em in anyway - they must have been in the passwd file */
278 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
282 if (bundle->radius.valid)
286 /* Disappeared from ppp.secret ??? */
292 auth_Validate(struct bundle *bundle, const char *name, const char *key)
294 /* Used by PAP routines */
298 char *vector[5], buff[LINE_LEN];
301 fp = OpenSecret(SECRETFILE);
305 while (fgets(buff, sizeof buff, fp)) {
309 buff[strlen(buff) - 1] = 0;
310 memset(vector, '\0', sizeof vector);
311 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
312 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
315 if (strcmp(vector[0], name) == 0) {
317 return auth_CheckPasswd(name, vector[1], key);
322 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
323 /* Look for the name without the leading domain */
335 if (Enabled(bundle, OPT_PASSWDAUTH))
336 return auth_CheckPasswd(name, "*", key);
339 return 0; /* Invalid */
343 auth_GetSecret(const char *name, size_t len)
345 /* Used by CHAP routines */
351 static char buff[LINE_LEN]; /* vector[] will point here when returned */
353 fp = OpenSecret(SECRETFILE);
359 while (fgets(buff, sizeof buff, fp)) {
363 n = strlen(buff) - 1;
365 buff[n] = '\0'; /* Trim the '\n' */
366 memset(vector, '\0', sizeof vector);
367 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
368 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
371 if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) {
377 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
378 /* Go back and look for the name without the leading domain */
379 len -= slash - name + 1;
386 return (NULL); /* Invalid */
390 AuthTimeout(void *vauthp)
392 struct authinfo *authp = (struct authinfo *)vauthp;
394 timer_Stop(&authp->authtimer);
395 if (--authp->retry > 0) {
397 (*authp->fn.req)(authp);
398 timer_Start(&authp->authtimer);
400 log_Printf(LogPHASE, "Auth: No response from server\n");
401 datalink_AuthNotOk(authp->physical->dl);
406 auth_Init(struct authinfo *authp, struct physical *p, auth_func req,
407 auth_func success, auth_func failure)
409 memset(authp, '\0', sizeof(struct authinfo));
410 authp->cfg.fsm.timeout = DEF_FSMRETRY;
411 authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES;
412 authp->cfg.fsm.maxtrm = 0; /* not used */
414 authp->fn.success = success;
415 authp->fn.failure = failure;
420 auth_StartReq(struct authinfo *authp)
422 timer_Stop(&authp->authtimer);
423 authp->authtimer.func = AuthTimeout;
424 authp->authtimer.name = "auth";
425 authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS;
426 authp->authtimer.arg = (void *)authp;
427 authp->retry = authp->cfg.fsm.maxreq;
429 (*authp->fn.req)(authp);
430 timer_Start(&authp->authtimer);
434 auth_StopTimer(struct authinfo *authp)
436 timer_Stop(&authp->authtimer);
440 auth_ReadHeader(struct authinfo *authp, struct mbuf *bp)
445 if (len >= sizeof authp->in.hdr) {
446 bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr);
447 if (len >= ntohs(authp->in.hdr.length))
449 authp->in.hdr.length = htons(0);
450 log_Printf(LogWARN, "auth_ReadHeader: Short packet (%u > %zu) !\n",
451 ntohs(authp->in.hdr.length), len);
453 authp->in.hdr.length = htons(0);
454 log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%u > %zu) !\n",
455 (int)(sizeof authp->in.hdr), len);
463 auth_ReadName(struct authinfo *authp, struct mbuf *bp, size_t len)
465 if (len > sizeof authp->in.name - 1)
466 log_Printf(LogWARN, "auth_ReadName: Name too long (%zu) !\n", len);
468 size_t mlen = m_length(bp);
471 log_Printf(LogWARN, "auth_ReadName: Short packet (%zu > %zu) !\n",
474 bp = mbuf_Read(bp, (u_char *)authp->in.name, len);
475 authp->in.name[len] = '\0';
480 *authp->in.name = '\0';