Deleted Added
full compact
auth.c (174870) auth.c (231994)
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.
6 *
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.
15 *
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.
27 *
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.
6 *
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.
15 *
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.
27 *
28 * $FreeBSD: head/usr.sbin/ppp/auth.c 174870 2007-12-22 19:29:32Z des $
28 * $FreeBSD: head/usr.sbin/ppp/auth.c 231994 2012-02-22 06:27:20Z kevlo $
29 */
30
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <sys/socket.h>
36#include <sys/un.h>
37
38#include <pwd.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <termios.h>
43#include <unistd.h>
44
45#ifndef NOPAM
46#include <security/pam_appl.h>
47#ifdef OPENPAM
48#include <security/openpam.h>
49#endif
50#endif /* !NOPAM */
51
52#include "layer.h"
53#include "mbuf.h"
54#include "defs.h"
55#include "log.h"
56#include "timer.h"
57#include "fsm.h"
58#include "iplist.h"
59#include "throughput.h"
60#include "slcompress.h"
61#include "lqr.h"
62#include "hdlc.h"
63#include "ncpaddr.h"
64#include "ipcp.h"
65#include "auth.h"
66#include "systems.h"
67#include "lcp.h"
68#include "ccp.h"
69#include "link.h"
70#include "descriptor.h"
71#include "chat.h"
72#include "proto.h"
73#include "filter.h"
74#include "mp.h"
75#ifndef NORADIUS
76#include "radius.h"
77#endif
78#include "cbcp.h"
79#include "chap.h"
80#include "async.h"
81#include "physical.h"
82#include "datalink.h"
83#include "ipv6cp.h"
84#include "ncp.h"
85#include "bundle.h"
86
87const char *
88Auth2Nam(u_short auth, u_char type)
89{
90 static char chap[10];
91
92 switch (auth) {
93 case PROTO_PAP:
94 return "PAP";
95 case PROTO_CHAP:
96 snprintf(chap, sizeof chap, "CHAP 0x%02x", type);
97 return chap;
98 case 0:
99 return "none";
100 }
101 return "unknown";
102}
103
104#if !defined(NOPAM) && !defined(OPENPAM)
105static int
106pam_conv(int n, const struct pam_message **msg, struct pam_response **resp,
107 void *data)
108{
109
110 if (n != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
111 return (PAM_CONV_ERR);
112 if ((*resp = malloc(sizeof(struct pam_response))) == NULL)
113 return (PAM_CONV_ERR);
114 (*resp)[0].resp = strdup((const char *)data);
115 (*resp)[0].resp_retcode = 0;
116
117 return ((*resp)[0].resp != NULL ? PAM_SUCCESS : PAM_CONV_ERR);
118}
119#endif /* !defined(NOPAM) && !defined(OPENPAM) */
120
121static int
122auth_CheckPasswd(const char *name, const char *data, const char *key)
123{
124 if (!strcmp(data, "*")) {
125#ifdef NOPAM
126 /* Then look up the real password database */
127 struct passwd *pw;
128 int result;
29 */
30
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <sys/socket.h>
36#include <sys/un.h>
37
38#include <pwd.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <termios.h>
43#include <unistd.h>
44
45#ifndef NOPAM
46#include <security/pam_appl.h>
47#ifdef OPENPAM
48#include <security/openpam.h>
49#endif
50#endif /* !NOPAM */
51
52#include "layer.h"
53#include "mbuf.h"
54#include "defs.h"
55#include "log.h"
56#include "timer.h"
57#include "fsm.h"
58#include "iplist.h"
59#include "throughput.h"
60#include "slcompress.h"
61#include "lqr.h"
62#include "hdlc.h"
63#include "ncpaddr.h"
64#include "ipcp.h"
65#include "auth.h"
66#include "systems.h"
67#include "lcp.h"
68#include "ccp.h"
69#include "link.h"
70#include "descriptor.h"
71#include "chat.h"
72#include "proto.h"
73#include "filter.h"
74#include "mp.h"
75#ifndef NORADIUS
76#include "radius.h"
77#endif
78#include "cbcp.h"
79#include "chap.h"
80#include "async.h"
81#include "physical.h"
82#include "datalink.h"
83#include "ipv6cp.h"
84#include "ncp.h"
85#include "bundle.h"
86
87const char *
88Auth2Nam(u_short auth, u_char type)
89{
90 static char chap[10];
91
92 switch (auth) {
93 case PROTO_PAP:
94 return "PAP";
95 case PROTO_CHAP:
96 snprintf(chap, sizeof chap, "CHAP 0x%02x", type);
97 return chap;
98 case 0:
99 return "none";
100 }
101 return "unknown";
102}
103
104#if !defined(NOPAM) && !defined(OPENPAM)
105static int
106pam_conv(int n, const struct pam_message **msg, struct pam_response **resp,
107 void *data)
108{
109
110 if (n != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
111 return (PAM_CONV_ERR);
112 if ((*resp = malloc(sizeof(struct pam_response))) == NULL)
113 return (PAM_CONV_ERR);
114 (*resp)[0].resp = strdup((const char *)data);
115 (*resp)[0].resp_retcode = 0;
116
117 return ((*resp)[0].resp != NULL ? PAM_SUCCESS : PAM_CONV_ERR);
118}
119#endif /* !defined(NOPAM) && !defined(OPENPAM) */
120
121static int
122auth_CheckPasswd(const char *name, const char *data, const char *key)
123{
124 if (!strcmp(data, "*")) {
125#ifdef NOPAM
126 /* Then look up the real password database */
127 struct passwd *pw;
128 int result;
129 char *cryptpw;
129
130
131 cryptpw = crypt(key, pw->pw_passwd);
130 result = (pw = getpwnam(name)) &&
132 result = (pw = getpwnam(name)) &&
131 !strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd);
133 (cryptpw == NULL || !strcmp(cryptpw, pw->pw_passwd));
132 endpwent();
133 return result;
134#else /* !NOPAM */
135 /* Then consult with PAM. */
136 pam_handle_t *pamh;
137 int status;
138
139 struct pam_conv pamc = {
140#ifdef OPENPAM
141 &openpam_nullconv, NULL
142#else
143 &pam_conv, key
144#endif
145 };
146
147 if (pam_start("ppp", name, &pamc, &pamh) != PAM_SUCCESS)
148 return (0);
149#ifdef OPENPAM
150 if ((status = pam_set_item(pamh, PAM_AUTHTOK, key)) == PAM_SUCCESS)
151#endif
152 status = pam_authenticate(pamh, 0);
153 pam_end(pamh, status);
154 return (status == PAM_SUCCESS);
155#endif /* !NOPAM */
156 }
157
158 return !strcmp(data, key);
159}
160
161int
162auth_SetPhoneList(const char *name, char *phone, int phonelen)
163{
164 FILE *fp;
165 int n, lineno;
166 char *vector[6], buff[LINE_LEN];
167 const char *slash;
168
169 fp = OpenSecret(SECRETFILE);
170 if (fp != NULL) {
171again:
172 lineno = 0;
173 while (fgets(buff, sizeof buff, fp)) {
174 lineno++;
175 if (buff[0] == '#')
176 continue;
177 buff[strlen(buff) - 1] = '\0';
178 memset(vector, '\0', sizeof vector);
179 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
180 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
181 if (n < 5)
182 continue;
183 if (strcmp(vector[0], name) == 0) {
184 CloseSecret(fp);
185 if (*vector[4] == '\0')
186 return 0;
187 strncpy(phone, vector[4], phonelen - 1);
188 phone[phonelen - 1] = '\0';
189 return 1; /* Valid */
190 }
191 }
192
193 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
194 /* Look for the name without the leading domain */
195 name = slash + 1;
196 rewind(fp);
197 goto again;
198 }
199
200 CloseSecret(fp);
201 }
202 *phone = '\0';
203 return 0;
204}
205
206int
207auth_Select(struct bundle *bundle, const char *name)
208{
209 FILE *fp;
210 int n, lineno;
211 char *vector[5], buff[LINE_LEN];
212 const char *slash;
213
214 if (*name == '\0') {
215 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
216 return 1;
217 }
218
219#ifndef NORADIUS
220 if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE &&
221 bundle->radius.ip.s_addr != RADIUS_INADDR_POOL) {
222 /* We've got a radius IP - it overrides everything */
223 if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip))
224 return 0;
225 ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr);
226 /* Continue with ppp.secret in case we've got a new label */
227 }
228#endif
229
230 fp = OpenSecret(SECRETFILE);
231 if (fp != NULL) {
232again:
233 lineno = 0;
234 while (fgets(buff, sizeof buff, fp)) {
235 lineno++;
236 if (buff[0] == '#')
237 continue;
238 buff[strlen(buff) - 1] = '\0';
239 memset(vector, '\0', sizeof vector);
240 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
241 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
242 if (n < 2)
243 continue;
244 if (strcmp(vector[0], name) == 0) {
245 CloseSecret(fp);
246#ifndef NORADIUS
247 if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) {
248#endif
249 if (n > 2 && *vector[2] && strcmp(vector[2], "*") &&
250 !ipcp_UseHisaddr(bundle, vector[2], 1))
251 return 0;
252 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
253#ifndef NORADIUS
254 }
255#endif
256 if (n > 3 && *vector[3] && strcmp(vector[3], "*"))
257 bundle_SetLabel(bundle, vector[3]);
258 return 1; /* Valid */
259 }
260 }
261
262 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
263 /* Look for the name without the leading domain */
264 name = slash + 1;
265 rewind(fp);
266 goto again;
267 }
268
269 CloseSecret(fp);
270 }
271
272#ifndef NOPASSWDAUTH
273 /* Let 'em in anyway - they must have been in the passwd file */
274 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
275 return 1;
276#else
277#ifndef NORADIUS
278 if (bundle->radius.valid)
279 return 1;
280#endif
281
282 /* Disappeared from ppp.secret ??? */
283 return 0;
284#endif
285}
286
287int
288auth_Validate(struct bundle *bundle, const char *name, const char *key)
289{
290 /* Used by PAP routines */
291
292 FILE *fp;
293 int n, lineno;
294 char *vector[5], buff[LINE_LEN];
295 const char *slash;
296
297 fp = OpenSecret(SECRETFILE);
298again:
299 lineno = 0;
300 if (fp != NULL) {
301 while (fgets(buff, sizeof buff, fp)) {
302 lineno++;
303 if (buff[0] == '#')
304 continue;
305 buff[strlen(buff) - 1] = 0;
306 memset(vector, '\0', sizeof vector);
307 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
308 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
309 if (n < 2)
310 continue;
311 if (strcmp(vector[0], name) == 0) {
312 CloseSecret(fp);
313 return auth_CheckPasswd(name, vector[1], key);
314 }
315 }
316 }
317
318 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
319 /* Look for the name without the leading domain */
320 name = slash + 1;
321 if (fp != NULL) {
322 rewind(fp);
323 goto again;
324 }
325 }
326
327 if (fp != NULL)
328 CloseSecret(fp);
329
330#ifndef NOPASSWDAUTH
331 if (Enabled(bundle, OPT_PASSWDAUTH))
332 return auth_CheckPasswd(name, "*", key);
333#endif
334
335 return 0; /* Invalid */
336}
337
338char *
339auth_GetSecret(const char *name, size_t len)
340{
341 /* Used by CHAP routines */
342
343 FILE *fp;
344 int n, lineno;
345 char *vector[5];
346 const char *slash;
347 static char buff[LINE_LEN]; /* vector[] will point here when returned */
348
349 fp = OpenSecret(SECRETFILE);
350 if (fp == NULL)
351 return (NULL);
352
353again:
354 lineno = 0;
355 while (fgets(buff, sizeof buff, fp)) {
356 lineno++;
357 if (buff[0] == '#')
358 continue;
359 n = strlen(buff) - 1;
360 if (buff[n] == '\n')
361 buff[n] = '\0'; /* Trim the '\n' */
362 memset(vector, '\0', sizeof vector);
363 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
364 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
365 if (n < 2)
366 continue;
367 if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) {
368 CloseSecret(fp);
369 return vector[1];
370 }
371 }
372
373 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
374 /* Go back and look for the name without the leading domain */
375 len -= slash - name + 1;
376 name = slash + 1;
377 rewind(fp);
378 goto again;
379 }
380
381 CloseSecret(fp);
382 return (NULL); /* Invalid */
383}
384
385static void
386AuthTimeout(void *vauthp)
387{
388 struct authinfo *authp = (struct authinfo *)vauthp;
389
390 timer_Stop(&authp->authtimer);
391 if (--authp->retry > 0) {
392 authp->id++;
393 (*authp->fn.req)(authp);
394 timer_Start(&authp->authtimer);
395 } else {
396 log_Printf(LogPHASE, "Auth: No response from server\n");
397 datalink_AuthNotOk(authp->physical->dl);
398 }
399}
400
401void
402auth_Init(struct authinfo *authp, struct physical *p, auth_func req,
403 auth_func success, auth_func failure)
404{
405 memset(authp, '\0', sizeof(struct authinfo));
406 authp->cfg.fsm.timeout = DEF_FSMRETRY;
407 authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES;
408 authp->cfg.fsm.maxtrm = 0; /* not used */
409 authp->fn.req = req;
410 authp->fn.success = success;
411 authp->fn.failure = failure;
412 authp->physical = p;
413}
414
415void
416auth_StartReq(struct authinfo *authp)
417{
418 timer_Stop(&authp->authtimer);
419 authp->authtimer.func = AuthTimeout;
420 authp->authtimer.name = "auth";
421 authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS;
422 authp->authtimer.arg = (void *)authp;
423 authp->retry = authp->cfg.fsm.maxreq;
424 authp->id = 1;
425 (*authp->fn.req)(authp);
426 timer_Start(&authp->authtimer);
427}
428
429void
430auth_StopTimer(struct authinfo *authp)
431{
432 timer_Stop(&authp->authtimer);
433}
434
435struct mbuf *
436auth_ReadHeader(struct authinfo *authp, struct mbuf *bp)
437{
438 size_t len;
439
440 len = m_length(bp);
441 if (len >= sizeof authp->in.hdr) {
442 bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr);
443 if (len >= ntohs(authp->in.hdr.length))
444 return bp;
445 authp->in.hdr.length = htons(0);
446 log_Printf(LogWARN, "auth_ReadHeader: Short packet (%u > %zu) !\n",
447 ntohs(authp->in.hdr.length), len);
448 } else {
449 authp->in.hdr.length = htons(0);
450 log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%u > %zu) !\n",
451 (int)(sizeof authp->in.hdr), len);
452 }
453
454 m_freem(bp);
455 return NULL;
456}
457
458struct mbuf *
459auth_ReadName(struct authinfo *authp, struct mbuf *bp, size_t len)
460{
461 if (len > sizeof authp->in.name - 1)
462 log_Printf(LogWARN, "auth_ReadName: Name too long (%zu) !\n", len);
463 else {
464 size_t mlen = m_length(bp);
465
466 if (len > mlen)
467 log_Printf(LogWARN, "auth_ReadName: Short packet (%zu > %zu) !\n",
468 len, mlen);
469 else {
470 bp = mbuf_Read(bp, (u_char *)authp->in.name, len);
471 authp->in.name[len] = '\0';
472 return bp;
473 }
474 }
475
476 *authp->in.name = '\0';
477 m_freem(bp);
478 return NULL;
479}
134 endpwent();
135 return result;
136#else /* !NOPAM */
137 /* Then consult with PAM. */
138 pam_handle_t *pamh;
139 int status;
140
141 struct pam_conv pamc = {
142#ifdef OPENPAM
143 &openpam_nullconv, NULL
144#else
145 &pam_conv, key
146#endif
147 };
148
149 if (pam_start("ppp", name, &pamc, &pamh) != PAM_SUCCESS)
150 return (0);
151#ifdef OPENPAM
152 if ((status = pam_set_item(pamh, PAM_AUTHTOK, key)) == PAM_SUCCESS)
153#endif
154 status = pam_authenticate(pamh, 0);
155 pam_end(pamh, status);
156 return (status == PAM_SUCCESS);
157#endif /* !NOPAM */
158 }
159
160 return !strcmp(data, key);
161}
162
163int
164auth_SetPhoneList(const char *name, char *phone, int phonelen)
165{
166 FILE *fp;
167 int n, lineno;
168 char *vector[6], buff[LINE_LEN];
169 const char *slash;
170
171 fp = OpenSecret(SECRETFILE);
172 if (fp != NULL) {
173again:
174 lineno = 0;
175 while (fgets(buff, sizeof buff, fp)) {
176 lineno++;
177 if (buff[0] == '#')
178 continue;
179 buff[strlen(buff) - 1] = '\0';
180 memset(vector, '\0', sizeof vector);
181 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
182 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
183 if (n < 5)
184 continue;
185 if (strcmp(vector[0], name) == 0) {
186 CloseSecret(fp);
187 if (*vector[4] == '\0')
188 return 0;
189 strncpy(phone, vector[4], phonelen - 1);
190 phone[phonelen - 1] = '\0';
191 return 1; /* Valid */
192 }
193 }
194
195 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
196 /* Look for the name without the leading domain */
197 name = slash + 1;
198 rewind(fp);
199 goto again;
200 }
201
202 CloseSecret(fp);
203 }
204 *phone = '\0';
205 return 0;
206}
207
208int
209auth_Select(struct bundle *bundle, const char *name)
210{
211 FILE *fp;
212 int n, lineno;
213 char *vector[5], buff[LINE_LEN];
214 const char *slash;
215
216 if (*name == '\0') {
217 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
218 return 1;
219 }
220
221#ifndef NORADIUS
222 if (bundle->radius.valid && bundle->radius.ip.s_addr != INADDR_NONE &&
223 bundle->radius.ip.s_addr != RADIUS_INADDR_POOL) {
224 /* We've got a radius IP - it overrides everything */
225 if (!ipcp_UseHisIPaddr(bundle, bundle->radius.ip))
226 return 0;
227 ipcp_Setup(&bundle->ncp.ipcp, bundle->radius.mask.s_addr);
228 /* Continue with ppp.secret in case we've got a new label */
229 }
230#endif
231
232 fp = OpenSecret(SECRETFILE);
233 if (fp != NULL) {
234again:
235 lineno = 0;
236 while (fgets(buff, sizeof buff, fp)) {
237 lineno++;
238 if (buff[0] == '#')
239 continue;
240 buff[strlen(buff) - 1] = '\0';
241 memset(vector, '\0', sizeof vector);
242 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
243 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
244 if (n < 2)
245 continue;
246 if (strcmp(vector[0], name) == 0) {
247 CloseSecret(fp);
248#ifndef NORADIUS
249 if (!bundle->radius.valid || bundle->radius.ip.s_addr == INADDR_NONE) {
250#endif
251 if (n > 2 && *vector[2] && strcmp(vector[2], "*") &&
252 !ipcp_UseHisaddr(bundle, vector[2], 1))
253 return 0;
254 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
255#ifndef NORADIUS
256 }
257#endif
258 if (n > 3 && *vector[3] && strcmp(vector[3], "*"))
259 bundle_SetLabel(bundle, vector[3]);
260 return 1; /* Valid */
261 }
262 }
263
264 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
265 /* Look for the name without the leading domain */
266 name = slash + 1;
267 rewind(fp);
268 goto again;
269 }
270
271 CloseSecret(fp);
272 }
273
274#ifndef NOPASSWDAUTH
275 /* Let 'em in anyway - they must have been in the passwd file */
276 ipcp_Setup(&bundle->ncp.ipcp, INADDR_NONE);
277 return 1;
278#else
279#ifndef NORADIUS
280 if (bundle->radius.valid)
281 return 1;
282#endif
283
284 /* Disappeared from ppp.secret ??? */
285 return 0;
286#endif
287}
288
289int
290auth_Validate(struct bundle *bundle, const char *name, const char *key)
291{
292 /* Used by PAP routines */
293
294 FILE *fp;
295 int n, lineno;
296 char *vector[5], buff[LINE_LEN];
297 const char *slash;
298
299 fp = OpenSecret(SECRETFILE);
300again:
301 lineno = 0;
302 if (fp != NULL) {
303 while (fgets(buff, sizeof buff, fp)) {
304 lineno++;
305 if (buff[0] == '#')
306 continue;
307 buff[strlen(buff) - 1] = 0;
308 memset(vector, '\0', sizeof vector);
309 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
310 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
311 if (n < 2)
312 continue;
313 if (strcmp(vector[0], name) == 0) {
314 CloseSecret(fp);
315 return auth_CheckPasswd(name, vector[1], key);
316 }
317 }
318 }
319
320 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
321 /* Look for the name without the leading domain */
322 name = slash + 1;
323 if (fp != NULL) {
324 rewind(fp);
325 goto again;
326 }
327 }
328
329 if (fp != NULL)
330 CloseSecret(fp);
331
332#ifndef NOPASSWDAUTH
333 if (Enabled(bundle, OPT_PASSWDAUTH))
334 return auth_CheckPasswd(name, "*", key);
335#endif
336
337 return 0; /* Invalid */
338}
339
340char *
341auth_GetSecret(const char *name, size_t len)
342{
343 /* Used by CHAP routines */
344
345 FILE *fp;
346 int n, lineno;
347 char *vector[5];
348 const char *slash;
349 static char buff[LINE_LEN]; /* vector[] will point here when returned */
350
351 fp = OpenSecret(SECRETFILE);
352 if (fp == NULL)
353 return (NULL);
354
355again:
356 lineno = 0;
357 while (fgets(buff, sizeof buff, fp)) {
358 lineno++;
359 if (buff[0] == '#')
360 continue;
361 n = strlen(buff) - 1;
362 if (buff[n] == '\n')
363 buff[n] = '\0'; /* Trim the '\n' */
364 memset(vector, '\0', sizeof vector);
365 if ((n = MakeArgs(buff, vector, VECSIZE(vector), PARSE_REDUCE)) < 0)
366 log_Printf(LogWARN, "%s: %d: Invalid line\n", SECRETFILE, lineno);
367 if (n < 2)
368 continue;
369 if (strlen(vector[0]) == len && strncmp(vector[0], name, len) == 0) {
370 CloseSecret(fp);
371 return vector[1];
372 }
373 }
374
375 if ((slash = strrchr(name, '\\')) != NULL && slash[1]) {
376 /* Go back and look for the name without the leading domain */
377 len -= slash - name + 1;
378 name = slash + 1;
379 rewind(fp);
380 goto again;
381 }
382
383 CloseSecret(fp);
384 return (NULL); /* Invalid */
385}
386
387static void
388AuthTimeout(void *vauthp)
389{
390 struct authinfo *authp = (struct authinfo *)vauthp;
391
392 timer_Stop(&authp->authtimer);
393 if (--authp->retry > 0) {
394 authp->id++;
395 (*authp->fn.req)(authp);
396 timer_Start(&authp->authtimer);
397 } else {
398 log_Printf(LogPHASE, "Auth: No response from server\n");
399 datalink_AuthNotOk(authp->physical->dl);
400 }
401}
402
403void
404auth_Init(struct authinfo *authp, struct physical *p, auth_func req,
405 auth_func success, auth_func failure)
406{
407 memset(authp, '\0', sizeof(struct authinfo));
408 authp->cfg.fsm.timeout = DEF_FSMRETRY;
409 authp->cfg.fsm.maxreq = DEF_FSMAUTHTRIES;
410 authp->cfg.fsm.maxtrm = 0; /* not used */
411 authp->fn.req = req;
412 authp->fn.success = success;
413 authp->fn.failure = failure;
414 authp->physical = p;
415}
416
417void
418auth_StartReq(struct authinfo *authp)
419{
420 timer_Stop(&authp->authtimer);
421 authp->authtimer.func = AuthTimeout;
422 authp->authtimer.name = "auth";
423 authp->authtimer.load = authp->cfg.fsm.timeout * SECTICKS;
424 authp->authtimer.arg = (void *)authp;
425 authp->retry = authp->cfg.fsm.maxreq;
426 authp->id = 1;
427 (*authp->fn.req)(authp);
428 timer_Start(&authp->authtimer);
429}
430
431void
432auth_StopTimer(struct authinfo *authp)
433{
434 timer_Stop(&authp->authtimer);
435}
436
437struct mbuf *
438auth_ReadHeader(struct authinfo *authp, struct mbuf *bp)
439{
440 size_t len;
441
442 len = m_length(bp);
443 if (len >= sizeof authp->in.hdr) {
444 bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr);
445 if (len >= ntohs(authp->in.hdr.length))
446 return bp;
447 authp->in.hdr.length = htons(0);
448 log_Printf(LogWARN, "auth_ReadHeader: Short packet (%u > %zu) !\n",
449 ntohs(authp->in.hdr.length), len);
450 } else {
451 authp->in.hdr.length = htons(0);
452 log_Printf(LogWARN, "auth_ReadHeader: Short packet header (%u > %zu) !\n",
453 (int)(sizeof authp->in.hdr), len);
454 }
455
456 m_freem(bp);
457 return NULL;
458}
459
460struct mbuf *
461auth_ReadName(struct authinfo *authp, struct mbuf *bp, size_t len)
462{
463 if (len > sizeof authp->in.name - 1)
464 log_Printf(LogWARN, "auth_ReadName: Name too long (%zu) !\n", len);
465 else {
466 size_t mlen = m_length(bp);
467
468 if (len > mlen)
469 log_Printf(LogWARN, "auth_ReadName: Short packet (%zu > %zu) !\n",
470 len, mlen);
471 else {
472 bp = mbuf_Read(bp, (u_char *)authp->in.name, len);
473 authp->in.name[len] = '\0';
474 return bp;
475 }
476 }
477
478 *authp->in.name = '\0';
479 m_freem(bp);
480 return NULL;
481}