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