1*b7041c07Sderaadt /* $OpenBSD: authenticate.c,v 1.29 2021/10/24 21:24:20 deraadt Exp $ */
2e802aa69Smillert
3e802aa69Smillert /*-
4e802aa69Smillert * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
5e802aa69Smillert *
6e802aa69Smillert * Redistribution and use in source and binary forms, with or without
7e802aa69Smillert * modification, are permitted provided that the following conditions
8e802aa69Smillert * are met:
9e802aa69Smillert * 1. Redistributions of source code must retain the above copyright
10e802aa69Smillert * notice, this list of conditions and the following disclaimer.
11e802aa69Smillert * 2. Redistributions in binary form must reproduce the above copyright
12e802aa69Smillert * notice, this list of conditions and the following disclaimer in the
13e802aa69Smillert * documentation and/or other materials provided with the distribution.
14e802aa69Smillert * 3. All advertising materials mentioning features or use of this software
15e802aa69Smillert * must display the following acknowledgement:
16e802aa69Smillert * This product includes software developed by Berkeley Software Design,
17e802aa69Smillert * Inc.
18e802aa69Smillert * 4. The name of Berkeley Software Design, Inc. may not be used to endorse
19e802aa69Smillert * or promote products derived from this software without specific prior
20e802aa69Smillert * written permission.
21e802aa69Smillert *
22e802aa69Smillert * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
23e802aa69Smillert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24e802aa69Smillert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25e802aa69Smillert * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
26e802aa69Smillert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27e802aa69Smillert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28e802aa69Smillert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29e802aa69Smillert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30e802aa69Smillert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31e802aa69Smillert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32e802aa69Smillert * SUCH DAMAGE.
33e802aa69Smillert *
34e802aa69Smillert * BSDI $From: authenticate.c,v 2.21 1999/09/08 22:33:26 prb Exp $
35e802aa69Smillert */
3669245ebdSmillert
37e802aa69Smillert #include <sys/stat.h>
38e802aa69Smillert
39e802aa69Smillert #include <ctype.h>
40e802aa69Smillert #include <err.h>
41e802aa69Smillert #include <fcntl.h>
4269245ebdSmillert #include <limits.h>
43e802aa69Smillert #include <login_cap.h>
44e802aa69Smillert #include <paths.h>
45e802aa69Smillert #include <pwd.h>
46e802aa69Smillert #include <stdarg.h>
47e802aa69Smillert #include <stdio.h>
48e802aa69Smillert #include <stdlib.h>
49e802aa69Smillert #include <string.h>
50e802aa69Smillert #include <syslog.h>
51e802aa69Smillert #include <unistd.h>
52e802aa69Smillert
53e802aa69Smillert #include <bsd_auth.h>
54e802aa69Smillert
55e802aa69Smillert static int _auth_checknologin(login_cap_t *, int);
56e802aa69Smillert
57e802aa69Smillert char *
auth_mkvalue(char * value)58e802aa69Smillert auth_mkvalue(char *value)
59e802aa69Smillert {
60e802aa69Smillert char *big, *p;
61e802aa69Smillert
62e802aa69Smillert big = malloc(strlen(value) * 4 + 1);
63e802aa69Smillert if (big == NULL)
64e802aa69Smillert return (NULL);
65e802aa69Smillert /*
66e802aa69Smillert * XXX - There should be a more standardized
67e802aa69Smillert * routine for doing this sort of thing.
68e802aa69Smillert */
69e802aa69Smillert for (p = big; *value; ++value) {
70e802aa69Smillert switch (*value) {
71e802aa69Smillert case '\r':
72e802aa69Smillert *p++ = '\\';
73e802aa69Smillert *p++ = 'r';
74e802aa69Smillert break;
75e802aa69Smillert case '\n':
76e802aa69Smillert *p++ = '\\';
77e802aa69Smillert *p++ = 'n';
78e802aa69Smillert break;
79e802aa69Smillert case '\\':
80e802aa69Smillert *p++ = '\\';
81e802aa69Smillert *p++ = *value;
82e802aa69Smillert break;
83e802aa69Smillert case '\t':
84e802aa69Smillert case ' ':
85e802aa69Smillert if (p == big)
86e802aa69Smillert *p++ = '\\';
87e802aa69Smillert *p++ = *value;
88e802aa69Smillert break;
89e802aa69Smillert default:
90dfe5467eSderaadt if (!isprint((unsigned char)*value)) {
91e802aa69Smillert *p++ = '\\';
92e802aa69Smillert *p++ = ((*value >> 6) & 0x3) + '0';
93e802aa69Smillert *p++ = ((*value >> 3) & 0x7) + '0';
94e802aa69Smillert *p++ = ((*value ) & 0x7) + '0';
95e802aa69Smillert } else
96e802aa69Smillert *p++ = *value;
97e802aa69Smillert break;
98e802aa69Smillert }
99e802aa69Smillert }
100e802aa69Smillert *p = '\0';
101e802aa69Smillert return (big);
102e802aa69Smillert }
103753e8795Sguenther DEF_WEAK(auth_mkvalue);
104e802aa69Smillert
105e802aa69Smillert void
auth_checknologin(login_cap_t * lc)106e802aa69Smillert auth_checknologin(login_cap_t *lc)
107e802aa69Smillert {
108e802aa69Smillert if (_auth_checknologin(lc, 1))
109e802aa69Smillert exit(1);
110e802aa69Smillert }
111753e8795Sguenther DEF_WEAK(auth_checknologin);
112e802aa69Smillert
113e802aa69Smillert static int
_auth_checknologin(login_cap_t * lc,int print)114e802aa69Smillert _auth_checknologin(login_cap_t *lc, int print)
115e802aa69Smillert {
116e802aa69Smillert struct stat sb;
117e802aa69Smillert char *nologin;
1182877ca5fSmpech int mustfree;
1192877ca5fSmpech
1202877ca5fSmpech if (login_getcapbool(lc, "ignorenologin", 0))
1212877ca5fSmpech return (0);
122e802aa69Smillert
123e802aa69Smillert /*
124e802aa69Smillert * If we fail to get the nologin file due to a database error,
125e802aa69Smillert * assume there should have been one...
126e802aa69Smillert */
1272877ca5fSmpech nologin = login_getcapstr(lc, "nologin", "", NULL);
1282877ca5fSmpech mustfree = nologin && *nologin != '\0';
1292877ca5fSmpech if (nologin == NULL)
1302877ca5fSmpech goto print_nologin;
1312877ca5fSmpech
1322877ca5fSmpech /* First try the nologin file specified in login.conf. */
1332877ca5fSmpech if (*nologin != '\0' && stat(nologin, &sb) == 0)
1342877ca5fSmpech goto print_nologin;
135122af69aSderaadt if (mustfree) {
1362877ca5fSmpech free(nologin);
137122af69aSderaadt mustfree = 0;
138122af69aSderaadt }
1392877ca5fSmpech
1402877ca5fSmpech /* If that doesn't exist try _PATH_NOLOGIN. */
1412877ca5fSmpech if (stat(_PATH_NOLOGIN, &sb) == 0) {
1422877ca5fSmpech nologin = _PATH_NOLOGIN;
1432877ca5fSmpech goto print_nologin;
1442877ca5fSmpech }
1452877ca5fSmpech
1462877ca5fSmpech /* Couldn't stat any nologin files, must be OK to login. */
1472877ca5fSmpech return (0);
1482877ca5fSmpech
1492877ca5fSmpech print_nologin:
150e802aa69Smillert if (print) {
1512877ca5fSmpech if (!nologin || *nologin == '\0' || auth_cat(nologin) == 0) {
1522877ca5fSmpech puts("Logins are not allowed at this time.");
153e802aa69Smillert fflush(stdout);
154e802aa69Smillert }
1552877ca5fSmpech }
1562877ca5fSmpech if (mustfree)
1572877ca5fSmpech free(nologin);
158e802aa69Smillert return (-1);
159e802aa69Smillert }
160e802aa69Smillert
161e802aa69Smillert int
auth_cat(char * file)162e802aa69Smillert auth_cat(char *file)
163e802aa69Smillert {
164e802aa69Smillert int fd, nchars;
165e802aa69Smillert char tbuf[8192];
166e802aa69Smillert
167*b7041c07Sderaadt if ((fd = open(file, O_RDONLY)) == -1)
168e802aa69Smillert return (0);
169e802aa69Smillert while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
170e802aa69Smillert (void)write(fileno(stdout), tbuf, nchars);
171e802aa69Smillert (void)close(fd);
172e802aa69Smillert return (1);
173e802aa69Smillert }
174753e8795Sguenther DEF_WEAK(auth_cat);
175e802aa69Smillert
176e802aa69Smillert int
_auth_validuser(const char * name)177a314d10bSderaadt _auth_validuser(const char *name)
178a314d10bSderaadt {
179a314d10bSderaadt /* User name must be specified and may not start with a '-'. */
180a314d10bSderaadt if (*name == '\0' || *name == '-') {
181a314d10bSderaadt syslog(LOG_ERR, "invalid user name %s", name);
182a314d10bSderaadt return 0;
183a314d10bSderaadt }
184a314d10bSderaadt return 1;
185a314d10bSderaadt }
186a314d10bSderaadt
187a314d10bSderaadt int
auth_approval(auth_session_t * as,login_cap_t * lc,char * name,char * type)188e802aa69Smillert auth_approval(auth_session_t *as, login_cap_t *lc, char *name, char *type)
189e802aa69Smillert {
190bb14a393Smoritz int close_on_exit, close_lc_on_exit, len;
191cd245bcaSmillert struct passwd pwstore, *pwd;
192cd245bcaSmillert char *approve, *s, path[PATH_MAX], pwbuf[_PW_BUF_LEN];
193e802aa69Smillert
194e802aa69Smillert pwd = NULL;
195e802aa69Smillert close_on_exit = as == NULL;
196e802aa69Smillert close_lc_on_exit = lc == NULL;
197e802aa69Smillert
198e802aa69Smillert if (as != NULL && name == NULL)
199e802aa69Smillert name = auth_getitem(as, AUTHV_NAME);
200e802aa69Smillert
201e802aa69Smillert if (as != NULL)
202e802aa69Smillert pwd = auth_getpwd(as);
203e802aa69Smillert
20420675415Sderaadt if (pwd == NULL) {
205cd245bcaSmillert if (name != NULL) {
206a314d10bSderaadt if (!_auth_validuser(name)) {
207a314d10bSderaadt warnx("cannot approve who we don't recognize");
208a314d10bSderaadt return (0);
209a314d10bSderaadt }
210cd245bcaSmillert getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
211cd245bcaSmillert } else {
212cd245bcaSmillert getpwuid_r(getuid(), &pwstore, pwbuf, sizeof(pwbuf),
213cd245bcaSmillert &pwd);
214cd245bcaSmillert if (pwd == NULL) {
21502d24a42Sderaadt syslog(LOG_ERR, "no such user id %u", getuid());
2169b9d2a55Sguenther warnx("cannot approve who we don't recognize");
217e802aa69Smillert return (0);
218e802aa69Smillert }
219e802aa69Smillert name = pwd->pw_name;
220e802aa69Smillert }
22120675415Sderaadt }
222e802aa69Smillert
223e802aa69Smillert if (name == NULL)
224e802aa69Smillert name = pwd->pw_name;
225e802aa69Smillert
226e802aa69Smillert if (lc == NULL) {
22769245ebdSmillert if (strlen(name) >= PATH_MAX) {
228e802aa69Smillert syslog(LOG_ERR, "username to login %.*s...",
22969245ebdSmillert PATH_MAX, name);
2309b9d2a55Sguenther warnx("username too long");
231e802aa69Smillert return (0);
232e802aa69Smillert }
233e802aa69Smillert if (pwd == NULL && (approve = strchr(name, '.')) != NULL) {
2345af14704Sderaadt strlcpy(path, name, sizeof path);
235e802aa69Smillert path[approve - name] = '\0';
236cd245bcaSmillert getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
237e802aa69Smillert }
238e802aa69Smillert lc = login_getclass(pwd ? pwd->pw_class : NULL);
239e802aa69Smillert if (lc == NULL) {
2409b9d2a55Sguenther warnx("unable to classify user");
241e802aa69Smillert return (0);
242e802aa69Smillert }
243e802aa69Smillert }
244e802aa69Smillert
245e802aa69Smillert if (!type)
246e802aa69Smillert type = LOGIN_DEFSERVICE;
247e802aa69Smillert else {
248e802aa69Smillert if (strncmp(type, "approve-", 8) == 0)
249e802aa69Smillert type += 8;
250e802aa69Smillert
251bb14a393Smoritz len = snprintf(path, sizeof(path), "approve-%s", type);
252bb14a393Smoritz if (len < 0 || len >= sizeof(path)) {
253bb14a393Smoritz if (close_lc_on_exit)
254bb14a393Smoritz login_close(lc);
255bb14a393Smoritz syslog(LOG_ERR, "approval path too long %.*s...",
25669245ebdSmillert PATH_MAX, type);
2579b9d2a55Sguenther warnx("approval script path too long");
258bb14a393Smoritz return (0);
259bb14a393Smoritz }
260e802aa69Smillert }
261e802aa69Smillert
262e802aa69Smillert if ((approve = login_getcapstr(lc, s = path, NULL, NULL)) == NULL)
263e802aa69Smillert approve = login_getcapstr(lc, s = "approve", NULL, NULL);
264e802aa69Smillert
265e802aa69Smillert if (approve && approve[0] != '/') {
266e802aa69Smillert if (close_lc_on_exit)
267e802aa69Smillert login_close(lc);
268e802aa69Smillert syslog(LOG_ERR, "Invalid %s script: %s", s, approve);
2699b9d2a55Sguenther warnx("invalid path to approval script");
270c89dc092Smpech free(approve);
271e802aa69Smillert return (0);
272e802aa69Smillert }
273e802aa69Smillert
274e802aa69Smillert if (as == NULL && (as = auth_open()) == NULL) {
275e802aa69Smillert if (close_lc_on_exit)
276e802aa69Smillert login_close(lc);
277e802aa69Smillert syslog(LOG_ERR, "%m");
2789b9d2a55Sguenther warn(NULL);
279c89dc092Smpech free(approve);
280e802aa69Smillert return (0);
281e802aa69Smillert }
282e802aa69Smillert
283e802aa69Smillert auth_setstate(as, AUTH_OKAY);
284e802aa69Smillert if (auth_setitem(as, AUTHV_NAME, name) < 0) {
285e802aa69Smillert syslog(LOG_ERR, "%m");
2869b9d2a55Sguenther warn(NULL);
287e802aa69Smillert goto out;
288e802aa69Smillert }
289c39118a5Smarkus if (auth_check_expire(as) < 0) /* is this account expired */
290e802aa69Smillert goto out;
291e802aa69Smillert if (_auth_checknologin(lc,
292e802aa69Smillert auth_getitem(as, AUTHV_INTERACTIVE) != NULL)) {
293e802aa69Smillert auth_setstate(as, (auth_getstate(as) & ~AUTH_ALLOW));
294e802aa69Smillert goto out;
295e802aa69Smillert }
296e802aa69Smillert if (login_getcapbool(lc, "requirehome", 0) && pwd && pwd->pw_dir &&
297e802aa69Smillert pwd->pw_dir[0]) {
298e802aa69Smillert struct stat sb;
299e802aa69Smillert
300df69c215Sderaadt if (stat(pwd->pw_dir, &sb) == -1 || !S_ISDIR(sb.st_mode) ||
301e802aa69Smillert (pwd->pw_uid && sb.st_uid == pwd->pw_uid &&
302e802aa69Smillert (sb.st_mode & S_IXUSR) == 0)) {
303e802aa69Smillert auth_setstate(as, (auth_getstate(as) & ~AUTH_ALLOW));
304e802aa69Smillert goto out;
305e802aa69Smillert }
306e802aa69Smillert }
307e802aa69Smillert if (approve)
308a314d10bSderaadt auth_call(as, approve, strrchr(approve, '/') + 1, "--", name,
3090ecd7014Smillert lc->lc_class, type, (char *)NULL);
310e802aa69Smillert
311e802aa69Smillert out:
312c89dc092Smpech free(approve);
313e802aa69Smillert if (close_lc_on_exit)
314e802aa69Smillert login_close(lc);
315e802aa69Smillert
316e802aa69Smillert if (close_on_exit)
317e802aa69Smillert return (auth_close(as));
318e802aa69Smillert return (auth_getstate(as) & AUTH_ALLOW);
319e802aa69Smillert }
320753e8795Sguenther DEF_WEAK(auth_approval);
321e802aa69Smillert
322e802aa69Smillert auth_session_t *
auth_usercheck(char * name,char * style,char * type,char * password)323e802aa69Smillert auth_usercheck(char *name, char *style, char *type, char *password)
324e802aa69Smillert {
32569245ebdSmillert char namebuf[LOGIN_NAME_MAX + 1 + NAME_MAX + 1];
326cd245bcaSmillert char pwbuf[_PW_BUF_LEN];
327e802aa69Smillert auth_session_t *as;
328e802aa69Smillert login_cap_t *lc;
329cd245bcaSmillert struct passwd pwstore, *pwd = NULL;
330fa843023Smillert char *slash;
331e802aa69Smillert
332a314d10bSderaadt if (!_auth_validuser(name))
333a314d10bSderaadt return (NULL);
334d57f22e5Smillert if (strlcpy(namebuf, name, sizeof(namebuf)) >= sizeof(namebuf))
335e802aa69Smillert return (NULL);
336e802aa69Smillert name = namebuf;
337e802aa69Smillert
338e802aa69Smillert /*
339e802aa69Smillert * Split up user:style names if we were not given a style
340e802aa69Smillert */
341e802aa69Smillert if (style == NULL && (style = strchr(name, ':')) != NULL)
342e802aa69Smillert *style++ = '\0';
343e802aa69Smillert
344e802aa69Smillert /*
345fa843023Smillert * Cope with user/instance. We are only using this to get
346fa843023Smillert * the class so it is okay if we strip a /root instance
347e802aa69Smillert * The actual login script will pay attention to the instance.
348e802aa69Smillert */
349cd245bcaSmillert getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
350cd245bcaSmillert if (pwd == NULL) {
351fa843023Smillert if ((slash = strchr(name, '/')) != NULL) {
352fa843023Smillert *slash = '\0';
353cd245bcaSmillert getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
354fa843023Smillert *slash = '/';
355e802aa69Smillert }
356e802aa69Smillert }
3570bc1d88dSmillert if ((lc = login_getclass(pwd ? pwd->pw_class : NULL)) == NULL)
358e802aa69Smillert return (NULL);
359e802aa69Smillert
360e802aa69Smillert if ((style = login_getstyle(lc, style, type)) == NULL) {
361e802aa69Smillert login_close(lc);
362e802aa69Smillert return (NULL);
363e802aa69Smillert }
364e802aa69Smillert
365e802aa69Smillert if (password) {
366e802aa69Smillert if ((as = auth_open()) == NULL) {
367e802aa69Smillert login_close(lc);
368e802aa69Smillert return (NULL);
369e802aa69Smillert }
370e802aa69Smillert auth_setitem(as, AUTHV_SERVICE, "response");
371e802aa69Smillert auth_setdata(as, "", 1);
372e802aa69Smillert auth_setdata(as, password, strlen(password) + 1);
373c41446b5Sdlg explicit_bzero(password, strlen(password));
374e802aa69Smillert } else
375e802aa69Smillert as = NULL;
3760ecd7014Smillert as = auth_verify(as, style, name, lc->lc_class, (char *)NULL);
377e802aa69Smillert login_close(lc);
378e802aa69Smillert return (as);
379e802aa69Smillert }
380753e8795Sguenther DEF_WEAK(auth_usercheck);
381e802aa69Smillert
382e802aa69Smillert int
auth_userokay(char * name,char * style,char * type,char * password)383e802aa69Smillert auth_userokay(char *name, char *style, char *type, char *password)
384e802aa69Smillert {
385e802aa69Smillert auth_session_t *as;
38608b57e3dSmillert
387e802aa69Smillert as = auth_usercheck(name, style, type, password);
388e802aa69Smillert
389e802aa69Smillert return (as != NULL ? auth_close(as) : 0);
390e802aa69Smillert }
391753e8795Sguenther DEF_WEAK(auth_userokay);
392e802aa69Smillert
393e802aa69Smillert auth_session_t *
auth_userchallenge(char * name,char * style,char * type,char ** challengep)394e802aa69Smillert auth_userchallenge(char *name, char *style, char *type, char **challengep)
395e802aa69Smillert {
39669245ebdSmillert char namebuf[LOGIN_NAME_MAX + 1 + NAME_MAX + 1];
397e802aa69Smillert auth_session_t *as;
398e802aa69Smillert login_cap_t *lc;
399cd245bcaSmillert struct passwd pwstore, *pwd = NULL;
400cd245bcaSmillert char *slash, pwbuf[_PW_BUF_LEN];
401e802aa69Smillert
402a314d10bSderaadt if (!_auth_validuser(name))
403a314d10bSderaadt return (NULL);
404e802aa69Smillert if (strlen(name) >= sizeof(namebuf))
405e802aa69Smillert return (NULL);
4065af14704Sderaadt strlcpy(namebuf, name, sizeof namebuf);
407e802aa69Smillert name = namebuf;
408e802aa69Smillert
409e802aa69Smillert /*
410e802aa69Smillert * Split up user:style names if we were not given a style
411e802aa69Smillert */
412e802aa69Smillert if (style == NULL && (style = strchr(name, ':')) != NULL)
413e802aa69Smillert *style++ = '\0';
414e802aa69Smillert
415e802aa69Smillert /*
416fa843023Smillert * Cope with user/instance. We are only using this to get
417fa843023Smillert * the class so it is okay if we strip a /root instance
418e802aa69Smillert * The actual login script will pay attention to the instance.
419e802aa69Smillert */
420cd245bcaSmillert getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
421cd245bcaSmillert if (pwd == NULL) {
422fa843023Smillert if ((slash = strchr(name, '/')) != NULL) {
423fa843023Smillert *slash = '\0';
424cd245bcaSmillert getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
425fa843023Smillert *slash = '/';
426e802aa69Smillert }
427e802aa69Smillert }
4280bc1d88dSmillert if ((lc = login_getclass(pwd ? pwd->pw_class : NULL)) == NULL)
429e802aa69Smillert return (NULL);
430e802aa69Smillert
431e802aa69Smillert if ((style = login_getstyle(lc, style, type)) == NULL ||
432e802aa69Smillert (as = auth_open()) == NULL) {
433e802aa69Smillert login_close(lc);
434e802aa69Smillert return (NULL);
435e802aa69Smillert }
436e802aa69Smillert if (auth_setitem(as, AUTHV_STYLE, style) < 0 ||
437e802aa69Smillert auth_setitem(as, AUTHV_NAME, name) < 0 ||
4380bc1d88dSmillert auth_setitem(as, AUTHV_CLASS, lc->lc_class) < 0) {
439e802aa69Smillert auth_close(as);
440e802aa69Smillert login_close(lc);
441e802aa69Smillert return (NULL);
442e802aa69Smillert }
443e802aa69Smillert login_close(lc);
444e802aa69Smillert *challengep = auth_challenge(as);
445e802aa69Smillert return (as);
446e802aa69Smillert }
447753e8795Sguenther DEF_WEAK(auth_userchallenge);
448e802aa69Smillert
449e802aa69Smillert int
auth_userresponse(auth_session_t * as,char * response,int more)450e802aa69Smillert auth_userresponse(auth_session_t *as, char *response, int more)
451e802aa69Smillert {
45269245ebdSmillert char path[PATH_MAX];
453e802aa69Smillert char *style, *name, *challenge, *class;
454bb14a393Smoritz int len;
455e802aa69Smillert
456e802aa69Smillert if (as == NULL)
457e802aa69Smillert return (0);
458e802aa69Smillert
459e802aa69Smillert auth_setstate(as, 0);
460e802aa69Smillert
461e802aa69Smillert if ((style = auth_getitem(as, AUTHV_STYLE)) == NULL ||
462a314d10bSderaadt (name = auth_getitem(as, AUTHV_NAME)) == NULL ||
463a314d10bSderaadt !_auth_validuser(name)) {
464e802aa69Smillert if (more == 0)
465e802aa69Smillert return (auth_close(as));
466e802aa69Smillert return(0);
467e802aa69Smillert }
468bb14a393Smoritz
469bb14a393Smoritz len = snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
470bb14a393Smoritz if (len < 0 || len >= sizeof(path)) {
471bb14a393Smoritz if (more == 0)
472bb14a393Smoritz return (auth_close(as));
473bb14a393Smoritz return (0);
474bb14a393Smoritz }
475bb14a393Smoritz
476e802aa69Smillert challenge = auth_getitem(as, AUTHV_CHALLENGE);
477e802aa69Smillert class = auth_getitem(as, AUTHV_CLASS);
478e802aa69Smillert
479e802aa69Smillert if (challenge)
480e802aa69Smillert auth_setdata(as, challenge, strlen(challenge) + 1);
481e802aa69Smillert else
482e802aa69Smillert auth_setdata(as, "", 1);
4832b0e3e01Smillert if (response) {
484e802aa69Smillert auth_setdata(as, response, strlen(response) + 1);
485c41446b5Sdlg explicit_bzero(response, strlen(response));
4862b0e3e01Smillert } else
487e802aa69Smillert auth_setdata(as, "", 1);
488e802aa69Smillert
489a314d10bSderaadt auth_call(as, path, style, "-s", "response", "--", name,
490a314d10bSderaadt class, (char *)NULL);
491e802aa69Smillert
492e802aa69Smillert /*
493e802aa69Smillert * If they authenticated then make sure they did not expire
494e802aa69Smillert */
495e802aa69Smillert if (auth_getstate(as) & AUTH_ALLOW)
496e802aa69Smillert auth_check_expire(as);
497e802aa69Smillert if (more == 0)
498e802aa69Smillert return (auth_close(as));
499e802aa69Smillert return (auth_getstate(as) & AUTH_ALLOW);
500e802aa69Smillert }
501753e8795Sguenther DEF_WEAK(auth_userresponse);
502e802aa69Smillert
503e802aa69Smillert /*
504e802aa69Smillert * Authenticate name with the specified style.
505e802aa69Smillert * If ``as'' is NULL a new session is formed with the default service.
506e802aa69Smillert * Returns NULL only if ``as'' is NULL and we were unable to allocate
507e802aa69Smillert * a new session.
508e802aa69Smillert *
509e802aa69Smillert * Use auth_close() or auth_getstate() to determine if the authentication
510e802aa69Smillert * worked.
511e802aa69Smillert */
512e802aa69Smillert auth_session_t *
auth_verify(auth_session_t * as,char * style,char * name,...)513e802aa69Smillert auth_verify(auth_session_t *as, char *style, char *name, ...)
514e802aa69Smillert {
515e802aa69Smillert va_list ap;
51669245ebdSmillert char path[PATH_MAX];
517e802aa69Smillert
518e802aa69Smillert if ((name == NULL || style == NULL) && as == NULL)
519a314d10bSderaadt return (NULL);
520e802aa69Smillert
521e802aa69Smillert if (as == NULL && (as = auth_open()) == NULL)
522e802aa69Smillert return (NULL);
523e802aa69Smillert auth_setstate(as, 0);
524e802aa69Smillert
525e802aa69Smillert if (style != NULL && auth_setitem(as, AUTHV_STYLE, style) < 0)
526e802aa69Smillert return (as);
527e802aa69Smillert
528e802aa69Smillert if (name != NULL && auth_setitem(as, AUTHV_NAME, name) < 0)
529e802aa69Smillert return (as);
530e802aa69Smillert
531e802aa69Smillert style = auth_getitem(as, AUTHV_STYLE);
532e802aa69Smillert name = auth_getitem(as, AUTHV_NAME);
533a314d10bSderaadt if (!_auth_validuser(name))
534a314d10bSderaadt return (as);
535e802aa69Smillert
536e802aa69Smillert snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
537e802aa69Smillert va_start(ap, name);
538e802aa69Smillert auth_set_va_list(as, ap);
539e802aa69Smillert auth_call(as, path, auth_getitem(as, AUTHV_STYLE), "-s",
540a314d10bSderaadt auth_getitem(as, AUTHV_SERVICE), "--", name, (char *)NULL);
5414bd92a99Smillert va_end(ap);
542e802aa69Smillert return (as);
543e802aa69Smillert }
544753e8795Sguenther DEF_WEAK(auth_verify);
545