xref: /netbsd-src/crypto/external/bsd/openssh/dist/auth-pam.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
1 /*-
2  * Copyright (c) 2002 Networks Associates Technology, Inc.
3  * All rights reserved.
4  *
5  * This software was developed for the FreeBSD Project by ThinkSec AS and
6  * NAI Labs, the Security Research Division of Network Associates, Inc.
7  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
8  * DARPA CHATS research program.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 /*
32  * Copyright (c) 2003,2004 Damien Miller <djm@mindrot.org>
33  * Copyright (c) 2003,2004 Darren Tucker <dtucker@zip.com.au>
34  *
35  * Permission to use, copy, modify, and distribute this software for any
36  * purpose with or without fee is hereby granted, provided that the above
37  * copyright notice and this permission notice appear in all copies.
38  *
39  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
40  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
41  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
42  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
44  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
45  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46  */
47 
48 /* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */
49 #include "includes.h"
50 /*
51  * NetBSD local changes
52  */
53 __RCSID("$NetBSD: auth-pam.c,v 1.14 2018/04/06 18:58:59 christos Exp $");
54 #undef USE_POSIX_THREADS /* Not yet */
55 #define HAVE_SECURITY_PAM_APPL_H
56 #define HAVE_PAM_GETENVLIST
57 #define HAVE_PAM_PUTENV
58 #define sshpam_const	const	/* LinuxPAM, OpenPAM */
59 #define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member)
60 #define mysig_t sig_t
61 void sshpam_password_change_required(int);
62 #define SSHD_PAM_SERVICE               getprogname()
63 /* end NetBSD local changes */
64 
65 #include <sys/types.h>
66 #include <sys/stat.h>
67 #include <sys/wait.h>
68 #include <sys/socket.h>
69 
70 #include <errno.h>
71 #include <signal.h>
72 #include <stdarg.h>
73 #include <string.h>
74 #include <unistd.h>
75 #include <pwd.h>
76 
77 #ifdef USE_PAM
78 #if defined(HAVE_SECURITY_PAM_APPL_H)
79 #include <security/pam_appl.h>
80 #elif defined (HAVE_PAM_PAM_APPL_H)
81 #include <pam/pam_appl.h>
82 #endif
83 
84 #ifndef __NetBSD__
85 /* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */
86 #ifdef PAM_SUN_CODEBASE
87 # define sshpam_const		/* Solaris, HP-UX, AIX */
88 #else
89 # define sshpam_const	const	/* LinuxPAM, OpenPAM */
90 #endif
91 
92 #if !defined(SSHD_PAM_SERVICE)
93 extern char *__progname;
94 # define SSHD_PAM_SERVICE               __progname
95 #endif
96 
97 
98 /* Ambiguity in spec: is it an array of pointers or a pointer to an array? */
99 #ifdef PAM_SUN_CODEBASE
100 # define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member)
101 #else
102 # define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member)
103 #endif
104 #endif
105 
106 #include "xmalloc.h"
107 #include "buffer.h"
108 #include "key.h"
109 #include "hostfile.h"
110 #include "auth.h"
111 #include "auth-pam.h"
112 #include "canohost.h"
113 #include "log.h"
114 #include "msg.h"
115 #include "packet.h"
116 #include "misc.h"
117 #include "servconf.h"
118 #include "channels.h"
119 #include "session.h"
120 #include "ssh2.h"
121 #include "auth-options.h"
122 #ifdef GSSAPI
123 #include "ssh-gss.h"
124 #endif
125 #include "monitor_wrap.h"
126 #include "pfilter.h"
127 
128 extern ServerOptions options;
129 extern Buffer loginmsg;
130 extern u_int utmp_len;
131 
132 /* so we don't silently change behaviour */
133 #ifdef USE_POSIX_THREADS
134 # error "USE_POSIX_THREADS replaced by UNSUPPORTED_POSIX_THREADS_HACK"
135 #endif
136 
137 /*
138  * Formerly known as USE_POSIX_THREADS, using this is completely unsupported
139  * and generally a bad idea.  Use at own risk and do not expect support if
140  * this breaks.
141  */
142 #ifdef UNSUPPORTED_POSIX_THREADS_HACK
143 #include <pthread.h>
144 /*
145  * Avoid namespace clash when *not* using pthreads for systems *with*
146  * pthreads, which unconditionally define pthread_t via sys/types.h
147  * (e.g. Linux)
148  */
149 typedef pthread_t sp_pthread_t;
150 #else
151 typedef pid_t sp_pthread_t;
152 # undef pthread_exit
153 # define pthread_create(a, b, c, d)    _ssh_compat_pthread_create(a, b, c, d)
154 # define pthread_exit(a)               _ssh_compat_pthread_exit(a)
155 # define pthread_cancel(a)             _ssh_compat_pthread_cancel(a)
156 # define pthread_join(a, b)            _ssh_compat_pthread_join(a, b)
157 #endif
158 
159 struct pam_ctxt {
160 	sp_pthread_t	 pam_thread;
161 	int		 pam_psock;
162 	int		 pam_csock;
163 	int		 pam_done;
164 };
165 
166 static void sshpam_free_ctx(void *);
167 static struct pam_ctxt *cleanup_ctxt;
168 
169 #ifndef UNSUPPORTED_POSIX_THREADS_HACK
170 /*
171  * Simulate threads with processes.
172  */
173 
174 static int sshpam_thread_status = -1;
175 static mysig_t sshpam_oldsig;
176 
177 static void
178 sshpam_sigchld_handler(int sig)
179 {
180 	signal(SIGCHLD, SIG_DFL);
181 	if (cleanup_ctxt == NULL)
182 		return;	/* handler called after PAM cleanup, shouldn't happen */
183 	if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
184 	    <= 0) {
185 		/* PAM thread has not exitted, privsep slave must have */
186 		kill(cleanup_ctxt->pam_thread, SIGTERM);
187 		while (waitpid(cleanup_ctxt->pam_thread,
188 		    &sshpam_thread_status, 0) == -1) {
189 			if (errno == EINTR)
190 				continue;
191 			return;
192 		}
193 	}
194 	if (WIFSIGNALED(sshpam_thread_status) &&
195 	    WTERMSIG(sshpam_thread_status) == SIGTERM)
196 		return;	/* terminated by pthread_cancel */
197 	if (!WIFEXITED(sshpam_thread_status))
198 		sigdie("PAM: authentication thread exited unexpectedly");
199 	if (WEXITSTATUS(sshpam_thread_status) != 0)
200 		sigdie("PAM: authentication thread exited uncleanly");
201 }
202 
203 /* ARGSUSED */
204 __dead static void
205 pthread_exit(void *value)
206 {
207 	_exit(0);
208 }
209 
210 /* ARGSUSED */
211 static int
212 pthread_create(sp_pthread_t *thread, const void *attr,
213     void *(*thread_start)(void *), void *arg)
214 {
215 	pid_t pid;
216 	struct pam_ctxt *ctx = arg;
217 
218 	sshpam_thread_status = -1;
219 	switch ((pid = fork())) {
220 	case -1:
221 		error("fork(): %s", strerror(errno));
222 		return (-1);
223 	case 0:
224 		close(ctx->pam_psock);
225 		ctx->pam_psock = -1;
226 		thread_start(arg);
227 		_exit(1);
228 	default:
229 		*thread = pid;
230 		close(ctx->pam_csock);
231 		ctx->pam_csock = -1;
232 		sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
233 		return (0);
234 	}
235 }
236 
237 static int
238 pthread_cancel(sp_pthread_t thread)
239 {
240 	signal(SIGCHLD, sshpam_oldsig);
241 	return (kill(thread, SIGTERM));
242 }
243 
244 /* ARGSUSED */
245 static int
246 pthread_join(sp_pthread_t thread, void **value)
247 {
248 	int status;
249 
250 	if (sshpam_thread_status != -1)
251 		return (sshpam_thread_status);
252 	signal(SIGCHLD, sshpam_oldsig);
253 	while (waitpid(thread, &status, 0) == -1) {
254 		if (errno == EINTR)
255 			continue;
256 		fatal("%s: waitpid: %s", __func__, strerror(errno));
257 	}
258 	return (status);
259 }
260 #endif
261 
262 
263 static pam_handle_t *sshpam_handle = NULL;
264 static int sshpam_err = 0;
265 static int sshpam_authenticated = 0;
266 static int sshpam_session_open = 0;
267 static int sshpam_cred_established = 0;
268 static int sshpam_account_status = -1;
269 static int sshpam_maxtries_reached = 0;
270 static char **sshpam_env = NULL;
271 static Authctxt *sshpam_authctxt = NULL;
272 static const char *sshpam_password = NULL;
273 
274 /* Some PAM implementations don't implement this */
275 #ifndef HAVE_PAM_GETENVLIST
276 static char **
277 pam_getenvlist(pam_handle_t *pamh)
278 {
279 	/*
280 	 * XXX - If necessary, we can still support envrionment passing
281 	 * for platforms without pam_getenvlist by searching for known
282 	 * env vars (e.g. KRB5CCNAME) from the PAM environment.
283 	 */
284 	 return NULL;
285 }
286 #endif
287 
288 /*
289  * Some platforms, notably Solaris, do not enforce password complexity
290  * rules during pam_chauthtok() if the real uid of the calling process
291  * is 0, on the assumption that it's being called by "passwd" run by root.
292  * This wraps pam_chauthtok and sets/restore the real uid so PAM will do
293  * the right thing.
294  */
295 #ifdef SSHPAM_CHAUTHTOK_NEEDS_RUID
296 static int
297 sshpam_chauthtok_ruid(pam_handle_t *pamh, int flags)
298 {
299 	int result;
300 
301 	if (sshpam_authctxt == NULL)
302 		fatal("PAM: sshpam_authctxt not initialized");
303 	if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1)
304 		fatal("%s: setreuid failed: %s", __func__, strerror(errno));
305 	result = pam_chauthtok(pamh, flags);
306 	if (setreuid(0, -1) == -1)
307 		fatal("%s: setreuid failed: %s", __func__, strerror(errno));
308 	return result;
309 }
310 # define pam_chauthtok(a,b)	(sshpam_chauthtok_ruid((a), (b)))
311 #endif
312 
313 void
314 sshpam_password_change_required(int reqd)
315 {
316 	extern struct sshauthopt *auth_opts;
317 	static int saved_port, saved_agent, saved_x11;
318 
319 	debug3("%s %d", __func__, reqd);
320 	if (sshpam_authctxt == NULL)
321 		fatal("%s: PAM authctxt not initialized", __func__);
322 	sshpam_authctxt->force_pwchange = reqd;
323 	if (reqd) {
324 		saved_port = auth_opts->permit_port_forwarding_flag;
325 		saved_agent = auth_opts->permit_agent_forwarding_flag;
326 		saved_x11 = auth_opts->permit_x11_forwarding_flag;
327 		auth_opts->permit_port_forwarding_flag = 0;
328 		auth_opts->permit_agent_forwarding_flag = 0;
329 		auth_opts->permit_x11_forwarding_flag = 0;
330 	} else {
331 		if (saved_port)
332 			auth_opts->permit_port_forwarding_flag = saved_port;
333 		if (saved_agent)
334 			auth_opts->permit_agent_forwarding_flag = saved_agent;
335 		if (saved_x11)
336 			auth_opts->permit_x11_forwarding_flag = saved_x11;
337 	}
338 }
339 
340 /* Import regular and PAM environment from subprocess */
341 static void
342 import_environments(Buffer *b)
343 {
344 	char *env;
345 	u_int i, num_env;
346 	int err;
347 
348 	debug3("PAM: %s entering", __func__);
349 
350 #ifndef UNSUPPORTED_POSIX_THREADS_HACK
351 	/* Import variables set by do_pam_account */
352 	sshpam_account_status = buffer_get_int(b);
353 	sshpam_password_change_required(buffer_get_int(b));
354 
355 	/* Import environment from subprocess */
356 	num_env = buffer_get_int(b);
357 	if (num_env > 1024)
358 		fatal("%s: received %u environment variables, expected <= 1024",
359 		    __func__, num_env);
360 	sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env));
361 	debug3("PAM: num env strings %d", num_env);
362 	for(i = 0; i < num_env; i++)
363 		sshpam_env[i] = buffer_get_string(b, NULL);
364 
365 	sshpam_env[num_env] = NULL;
366 
367 	/* Import PAM environment from subprocess */
368 	num_env = buffer_get_int(b);
369 	debug("PAM: num PAM env strings %d", num_env);
370 	for(i = 0; i < num_env; i++) {
371 		env = buffer_get_string(b, NULL);
372 
373 #ifdef HAVE_PAM_PUTENV
374 		/* Errors are not fatal here */
375 		if ((err = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) {
376 			error("PAM: pam_putenv: %s",
377 			    pam_strerror(sshpam_handle, sshpam_err));
378 		}
379 #endif
380 	}
381 #endif
382 }
383 
384 /*
385  * Conversation function for authentication thread.
386  */
387 static int
388 sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
389     struct pam_response **resp, void *data)
390 {
391 	Buffer buffer;
392 	struct pam_ctxt *ctxt;
393 	struct pam_response *reply;
394 	int i;
395 
396 	debug3("PAM: %s entering, %d messages", __func__, n);
397 	*resp = NULL;
398 
399 	if (data == NULL) {
400 		error("PAM: conversation function passed a null context");
401 		return (PAM_CONV_ERR);
402 	}
403 	ctxt = data;
404 	if (n <= 0 || n > PAM_MAX_NUM_MSG)
405 		return (PAM_CONV_ERR);
406 
407 	if ((reply = calloc(n, sizeof(*reply))) == NULL)
408 		return (PAM_CONV_ERR);
409 
410 	buffer_init(&buffer);
411 	for (i = 0; i < n; ++i) {
412 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
413 		case PAM_PROMPT_ECHO_OFF:
414 		case PAM_PROMPT_ECHO_ON:
415 			buffer_put_cstring(&buffer,
416 			    PAM_MSG_MEMBER(msg, i, msg));
417 			if (ssh_msg_send(ctxt->pam_csock,
418 			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
419 				goto fail;
420 			if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1)
421 				goto fail;
422 			if (buffer_get_char(&buffer) != PAM_AUTHTOK)
423 				goto fail;
424 			reply[i].resp = buffer_get_string(&buffer, NULL);
425 			break;
426 		case PAM_ERROR_MSG:
427 		case PAM_TEXT_INFO:
428 			buffer_put_cstring(&buffer,
429 			    PAM_MSG_MEMBER(msg, i, msg));
430 			if (ssh_msg_send(ctxt->pam_csock,
431 			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
432 				goto fail;
433 			break;
434 		default:
435 			goto fail;
436 		}
437 		buffer_clear(&buffer);
438 	}
439 	buffer_free(&buffer);
440 	*resp = reply;
441 	return (PAM_SUCCESS);
442 
443  fail:
444 	for(i = 0; i < n; i++) {
445 		free(reply[i].resp);
446 	}
447 	free(reply);
448 	buffer_free(&buffer);
449 	return (PAM_CONV_ERR);
450 }
451 
452 /*
453  * Authentication thread.
454  */
455 static void *
456 sshpam_thread(void *ctxtp)
457 {
458 	struct pam_ctxt *ctxt = ctxtp;
459 	Buffer buffer;
460 	struct pam_conv sshpam_conv;
461 	int flags = (options.permit_empty_passwd == 0 ?
462 	    PAM_DISALLOW_NULL_AUTHTOK : 0);
463 #ifndef UNSUPPORTED_POSIX_THREADS_HACK
464 	extern char **environ;
465 	char **env_from_pam;
466 	u_int i;
467 	const char *pam_user;
468 	const char **ptr_pam_user = &pam_user;
469 	char *tz = getenv("TZ");
470 
471 	sshpam_err = pam_get_item(sshpam_handle, PAM_USER,
472 	    (sshpam_const void **)ptr_pam_user);
473 	if (sshpam_err != PAM_SUCCESS)
474 		goto auth_fail;
475 
476 	environ[0] = NULL;
477 	if (tz != NULL)
478 		if (setenv("TZ", tz, 1) == -1)
479 			error("PAM: could not set TZ environment: %s",
480 			    strerror(errno));
481 
482 	if (sshpam_authctxt != NULL) {
483 		setproctitle("%s [pam]",
484 		    sshpam_authctxt->valid ? pam_user : "unknown");
485 	}
486 #endif
487 
488 	sshpam_conv.conv = sshpam_thread_conv;
489 	sshpam_conv.appdata_ptr = ctxt;
490 
491 	if (sshpam_authctxt == NULL)
492 		fatal("%s: PAM authctxt not initialized", __func__);
493 
494 	buffer_init(&buffer);
495 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
496 	    (const void *)&sshpam_conv);
497 	if (sshpam_err != PAM_SUCCESS)
498 		goto auth_fail;
499 	sshpam_err = pam_authenticate(sshpam_handle, flags);
500 	if (sshpam_err == PAM_MAXTRIES)
501 		sshpam_set_maxtries_reached(1);
502 	if (sshpam_err != PAM_SUCCESS)
503 		goto auth_fail;
504 
505 	if (!do_pam_account()) {
506 		sshpam_err = PAM_ACCT_EXPIRED;
507 		goto auth_fail;
508 	}
509 	if (sshpam_authctxt->force_pwchange) {
510 		sshpam_err = pam_chauthtok(sshpam_handle,
511 		    PAM_CHANGE_EXPIRED_AUTHTOK);
512 		if (sshpam_err != PAM_SUCCESS)
513 			goto auth_fail;
514 		sshpam_password_change_required(0);
515 	}
516 
517 	buffer_put_cstring(&buffer, "OK");
518 
519 #ifndef UNSUPPORTED_POSIX_THREADS_HACK
520 	/* Export variables set by do_pam_account */
521 	buffer_put_int(&buffer, sshpam_account_status);
522 	buffer_put_int(&buffer, sshpam_authctxt->force_pwchange);
523 
524 	/* Export any environment strings set in child */
525 	for(i = 0; environ[i] != NULL; i++)
526 		; /* Count */
527 	buffer_put_int(&buffer, i);
528 	for(i = 0; environ[i] != NULL; i++)
529 		buffer_put_cstring(&buffer, environ[i]);
530 
531 	/* Export any environment strings set by PAM in child */
532 	env_from_pam = pam_getenvlist(sshpam_handle);
533 	for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
534 		; /* Count */
535 	buffer_put_int(&buffer, i);
536 	for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
537 		buffer_put_cstring(&buffer, env_from_pam[i]);
538 #endif /* UNSUPPORTED_POSIX_THREADS_HACK */
539 
540 	/* XXX - can't do much about an error here */
541 	ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer);
542 	buffer_free(&buffer);
543 	pthread_exit(NULL);
544 
545  auth_fail:
546 	buffer_put_cstring(&buffer,
547 	    pam_strerror(sshpam_handle, sshpam_err));
548 	/* XXX - can't do much about an error here */
549 	if (sshpam_err == PAM_ACCT_EXPIRED)
550 		ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer);
551 	else if (sshpam_maxtries_reached)
552 		ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, &buffer);
553 	else
554 		ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
555 	buffer_free(&buffer);
556 	pthread_exit(NULL);
557 
558 	return (NULL); /* Avoid warning for non-pthread case */
559 }
560 
561 void
562 sshpam_thread_cleanup(void)
563 {
564 	struct pam_ctxt *ctxt = cleanup_ctxt;
565 
566 	debug3("PAM: %s entering", __func__);
567 	if (ctxt != NULL && ctxt->pam_thread != 0) {
568 		pthread_cancel(ctxt->pam_thread);
569 		pthread_join(ctxt->pam_thread, NULL);
570 		close(ctxt->pam_psock);
571 		close(ctxt->pam_csock);
572 		memset(ctxt, 0, sizeof(*ctxt));
573 		cleanup_ctxt = NULL;
574 	}
575 }
576 
577 static int
578 sshpam_null_conv(int n, sshpam_const struct pam_message **msg,
579     struct pam_response **resp, void *data)
580 {
581 	debug3("PAM: %s entering, %d messages", __func__, n);
582 	return (PAM_CONV_ERR);
583 }
584 
585 static struct pam_conv null_conv = { sshpam_null_conv, NULL };
586 
587 static int
588 sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
589     struct pam_response **resp, void *data)
590 {
591 	struct pam_response *reply;
592 	int i;
593 	size_t len;
594 
595 	debug3("PAM: %s called with %d messages", __func__, n);
596 	*resp = NULL;
597 
598 	if (n <= 0 || n > PAM_MAX_NUM_MSG)
599 		return (PAM_CONV_ERR);
600 
601 	if ((reply = calloc(n, sizeof(*reply))) == NULL)
602 		return (PAM_CONV_ERR);
603 
604 	for (i = 0; i < n; ++i) {
605 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
606 		case PAM_ERROR_MSG:
607 		case PAM_TEXT_INFO:
608 			len = strlen(PAM_MSG_MEMBER(msg, i, msg));
609 			buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len);
610 			buffer_append(&loginmsg, "\n", 1 );
611 			reply[i].resp_retcode = PAM_SUCCESS;
612 			break;
613 		default:
614 			goto fail;
615 		}
616 	}
617 	*resp = reply;
618 	return (PAM_SUCCESS);
619 
620  fail:
621 	for(i = 0; i < n; i++) {
622 		free(reply[i].resp);
623 	}
624 	free(reply);
625 	return (PAM_CONV_ERR);
626 }
627 
628 static struct pam_conv store_conv = { sshpam_store_conv, NULL };
629 
630 void
631 sshpam_cleanup(void)
632 {
633 	if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor()))
634 		return;
635 	debug("PAM: cleanup");
636 	pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
637 	if (sshpam_session_open) {
638 		debug("PAM: closing session");
639 		pam_close_session(sshpam_handle, PAM_SILENT);
640 		sshpam_session_open = 0;
641 	}
642 	if (sshpam_cred_established) {
643 		debug("PAM: deleting credentials");
644 		pam_setcred(sshpam_handle, PAM_DELETE_CRED);
645 		sshpam_cred_established = 0;
646 	}
647 	sshpam_authenticated = 0;
648 	pam_end(sshpam_handle, sshpam_err);
649 	sshpam_handle = NULL;
650 }
651 
652 static int
653 sshpam_init(Authctxt *authctxt)
654 {
655 	const char *pam_rhost, *pam_user, *user = authctxt->user;
656 	const char **ptr_pam_user = &pam_user;
657 	struct ssh *ssh = active_state; /* XXX */
658 
659 	if (sshpam_handle != NULL) {
660 		/* We already have a PAM context; check if the user matches */
661 		sshpam_err = pam_get_item(sshpam_handle,
662 		    PAM_USER, (sshpam_const void **)ptr_pam_user);
663 		if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
664 			return (0);
665 		pam_end(sshpam_handle, sshpam_err);
666 		sshpam_handle = NULL;
667 	}
668 	debug("PAM: initializing for \"%s\"", user);
669 	sshpam_err =
670 	    pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
671 	sshpam_authctxt = authctxt;
672 
673 	if (sshpam_err != PAM_SUCCESS) {
674 		pam_end(sshpam_handle, sshpam_err);
675 		sshpam_handle = NULL;
676 		return (-1);
677 	}
678 	pam_rhost = auth_get_canonical_hostname(ssh, options.use_dns);
679 	debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
680 	sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
681 	if (sshpam_err != PAM_SUCCESS) {
682 		pam_end(sshpam_handle, sshpam_err);
683 		sshpam_handle = NULL;
684 		return (-1);
685 	}
686 #ifdef PAM_TTY_KLUDGE
687 	/*
688 	 * Some silly PAM modules (e.g. pam_time) require a TTY to operate.
689 	 * sshd doesn't set the tty until too late in the auth process and
690 	 * may not even set one (for tty-less connections)
691 	 */
692 	debug("PAM: setting PAM_TTY to \"ssh\"");
693 	sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, "ssh");
694 	if (sshpam_err != PAM_SUCCESS) {
695 		pam_end(sshpam_handle, sshpam_err);
696 		sshpam_handle = NULL;
697 		return (-1);
698 	}
699 #endif
700 	return (0);
701 }
702 
703 static void *
704 sshpam_init_ctx(Authctxt *authctxt)
705 {
706 	struct pam_ctxt *ctxt;
707 	int socks[2];
708 
709 	debug3("PAM: %s entering", __func__);
710 	/*
711 	 * Refuse to start if we don't have PAM enabled or do_pam_account
712 	 * has previously failed.
713 	 */
714 	if (!options.use_pam || sshpam_account_status == 0)
715 		return NULL;
716 
717 	/* Initialize PAM */
718 	if (sshpam_init(authctxt) == -1) {
719 		error("PAM: initialization failed");
720 		return (NULL);
721 	}
722 
723 	ctxt = xcalloc(1, sizeof *ctxt);
724 
725 	/* Start the authentication thread */
726 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
727 		error("PAM: failed create sockets: %s", strerror(errno));
728 		free(ctxt);
729 		return (NULL);
730 	}
731 	ctxt->pam_psock = socks[0];
732 	ctxt->pam_csock = socks[1];
733 	if (pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt) == -1) {
734 		error("PAM: failed to start authentication thread: %s",
735 		    strerror(errno));
736 		close(socks[0]);
737 		close(socks[1]);
738 		free(ctxt);
739 		return (NULL);
740 	}
741 	cleanup_ctxt = ctxt;
742 	return (ctxt);
743 }
744 
745 static int
746 sshpam_query(void *ctx, char **name, char **info,
747     u_int *num, char ***prompts, u_int **echo_on)
748 {
749 	struct ssh *ssh = active_state; /* XXX */
750 	Buffer buffer;
751 	struct pam_ctxt *ctxt = ctx;
752 	size_t plen;
753 	u_char type;
754 	char *msg;
755 	size_t len, mlen;
756 
757 	debug3("PAM: %s entering", __func__);
758 	buffer_init(&buffer);
759 	*name = xstrdup("");
760 	*info = xstrdup("");
761 	*prompts = xmalloc(sizeof(char *));
762 	**prompts = NULL;
763 	plen = 0;
764 	*echo_on = xmalloc(sizeof(u_int));
765 	while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
766 		type = buffer_get_char(&buffer);
767 		msg = buffer_get_string(&buffer, NULL);
768 		mlen = strlen(msg);
769 		switch (type) {
770 		case PAM_PROMPT_ECHO_ON:
771 		case PAM_PROMPT_ECHO_OFF:
772 			*num = 1;
773 			len = plen + mlen + 1;
774 			**prompts = xreallocarray(**prompts, 1, len);
775 			strlcpy(**prompts + plen, msg, len - plen);
776 			plen += mlen;
777 			**echo_on = (type == PAM_PROMPT_ECHO_ON);
778 			free(msg);
779 			return (0);
780 		case PAM_ERROR_MSG:
781 		case PAM_TEXT_INFO:
782 			/* accumulate messages */
783 			len = plen + mlen + 2;
784 			**prompts = xreallocarray(**prompts, 1, len);
785 			strlcpy(**prompts + plen, msg, len - plen);
786 			plen += mlen;
787 			strlcat(**prompts + plen, "\n", len - plen);
788 			plen++;
789 			free(msg);
790 			break;
791 		case PAM_ACCT_EXPIRED:
792 		case PAM_MAXTRIES:
793 			if (type == PAM_ACCT_EXPIRED)
794 				sshpam_account_status = 0;
795 			if (type == PAM_MAXTRIES)
796 				sshpam_set_maxtries_reached(1);
797 			/* FALLTHROUGH */
798 		case PAM_AUTH_ERR:
799 			debug3("PAM: %s", pam_strerror(sshpam_handle, type));
800 			if (**prompts != NULL && strlen(**prompts) != 0) {
801 				*info = **prompts;
802 				**prompts = NULL;
803 				*num = 0;
804 				**echo_on = 0;
805 				ctxt->pam_done = -1;
806 				free(msg);
807 				return 0;
808 			}
809 			/* FALLTHROUGH */
810 		case PAM_SUCCESS:
811 			if (**prompts != NULL) {
812 				/* drain any accumulated messages */
813 				debug("PAM: %s", **prompts);
814 				buffer_append(&loginmsg, **prompts,
815 				    strlen(**prompts));
816 				free(**prompts);
817 				**prompts = NULL;
818 			}
819 			if (type == PAM_SUCCESS) {
820 				if (!sshpam_authctxt->valid ||
821 				    (sshpam_authctxt->pw->pw_uid == 0 &&
822 				    options.permit_root_login != PERMIT_YES))
823 					fatal("Internal error: PAM auth "
824 					    "succeeded when it should have "
825 					    "failed");
826 				import_environments(&buffer);
827 				*num = 0;
828 				**echo_on = 0;
829 				ctxt->pam_done = 1;
830 				free(msg);
831 				return (0);
832 			}
833 			error("PAM: %s for %s%.100s from %.100s", msg,
834 			    sshpam_authctxt->valid ? "" : "illegal user ",
835 			    sshpam_authctxt->user,
836 			    auth_get_canonical_hostname(ssh, options.use_dns));
837 			/* FALLTHROUGH */
838 		default:
839 			*num = 0;
840 			**echo_on = 0;
841 			free(msg);
842 			ctxt->pam_done = -1;
843 			return (-1);
844 		}
845 	}
846 	return (-1);
847 }
848 
849 /*
850  * Returns a junk password of identical length to that the user supplied.
851  * Used to mitigate timing attacks against crypt(3)/PAM stacks that
852  * vary processing time in proportion to password length.
853  */
854 static char *
855 fake_password(const char *wire_password)
856 {
857 	const char junk[] = "\b\n\r\177INCORRECT";
858 	char *ret = NULL;
859 	size_t i, l = wire_password != NULL ? strlen(wire_password) : 0;
860 
861 	if (l >= INT_MAX)
862 		fatal("%s: password length too long: %zu", __func__, l);
863 
864 	ret = malloc(l + 1);
865 	if (ret == NULL)
866 		return NULL;
867 	for (i = 0; i < l; i++)
868 		ret[i] = junk[i % (sizeof(junk) - 1)];
869 	ret[i] = '\0';
870 	return ret;
871 }
872 
873 /* XXX - see also comment in auth-chall.c:verify_response */
874 static int
875 sshpam_respond(void *ctx, u_int num, char **resp)
876 {
877 	Buffer buffer;
878 	struct pam_ctxt *ctxt = ctx;
879 	char *fake;
880 
881 	debug2("PAM: %s entering, %u responses", __func__, num);
882 	switch (ctxt->pam_done) {
883 	case 1:
884 		sshpam_authenticated = 1;
885 		return (0);
886 	case 0:
887 		break;
888 	default:
889 		return (-1);
890 	}
891 	if (num != 1) {
892 		error("PAM: expected one response, got %u", num);
893 		return (-1);
894 	}
895 	buffer_init(&buffer);
896 	if (sshpam_authctxt->valid &&
897 	    (sshpam_authctxt->pw->pw_uid != 0 ||
898 	    options.permit_root_login == PERMIT_YES))
899 		buffer_put_cstring(&buffer, *resp);
900 	else {
901 		fake = fake_password(*resp);
902 		buffer_put_cstring(&buffer, fake);
903 		free(fake);
904 	}
905 	if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
906 		buffer_free(&buffer);
907 		return (-1);
908 	}
909 	buffer_free(&buffer);
910 	return (1);
911 }
912 
913 static void
914 sshpam_free_ctx(void *ctxtp)
915 {
916 	struct pam_ctxt *ctxt = ctxtp;
917 
918 	debug3("PAM: %s entering", __func__);
919 	sshpam_thread_cleanup();
920 	free(ctxt);
921 	/*
922 	 * We don't call sshpam_cleanup() here because we may need the PAM
923 	 * handle at a later stage, e.g. when setting up a session.  It's
924 	 * still on the cleanup list, so pam_end() *will* be called before
925 	 * the server process terminates.
926 	 */
927 }
928 
929 KbdintDevice sshpam_device = {
930 	"pam",
931 	sshpam_init_ctx,
932 	sshpam_query,
933 	sshpam_respond,
934 	sshpam_free_ctx
935 };
936 
937 KbdintDevice mm_sshpam_device = {
938 	"pam",
939 	mm_sshpam_init_ctx,
940 	mm_sshpam_query,
941 	mm_sshpam_respond,
942 	mm_sshpam_free_ctx
943 };
944 
945 /*
946  * This replaces auth-pam.c
947  */
948 void
949 start_pam(Authctxt *authctxt)
950 {
951 	if (!options.use_pam)
952 		fatal("PAM: initialisation requested when UsePAM=no");
953 
954 	if (sshpam_init(authctxt) == -1)
955 		fatal("PAM: initialisation failed");
956 }
957 
958 void
959 finish_pam(void)
960 {
961 	sshpam_cleanup();
962 }
963 
964 static void
965 expose_authinfo(const char *caller)
966 {
967 	char *auth_info;
968 
969 	/*
970 	 * Expose authentication information to PAM.
971 	 * The enviornment variable is versioned. Please increment the
972 	 * version suffix if the format of session_info changes.
973 	 */
974 	if (sshpam_authctxt->session_info == NULL)
975 		auth_info = xstrdup("");
976 	else if ((auth_info = sshbuf_dup_string(
977 	    sshpam_authctxt->session_info)) == NULL)
978 		fatal("%s: sshbuf_dup_string failed", __func__);
979 
980 	debug2("%s: auth information in SSH_AUTH_INFO_0", caller);
981 	do_pam_putenv("SSH_AUTH_INFO_0", auth_info);
982 	free(auth_info);
983 }
984 
985 u_int
986 do_pam_account(void)
987 {
988 	debug("%s: called", __func__);
989 	if (sshpam_account_status != -1)
990 		return (sshpam_account_status);
991 
992 	expose_authinfo(__func__);
993 
994 	sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
995 	debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
996 	    pam_strerror(sshpam_handle, sshpam_err));
997 
998 	if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
999 		sshpam_account_status = 0;
1000 		return (sshpam_account_status);
1001 	}
1002 
1003 	if (sshpam_err == PAM_NEW_AUTHTOK_REQD)
1004 		sshpam_password_change_required(1);
1005 
1006 	sshpam_account_status = 1;
1007 	return (sshpam_account_status);
1008 }
1009 
1010 void
1011 do_pam_setcred(int init)
1012 {
1013 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1014 	    (const void *)&store_conv);
1015 	if (sshpam_err != PAM_SUCCESS)
1016 		fatal("PAM: failed to set PAM_CONV: %s",
1017 		    pam_strerror(sshpam_handle, sshpam_err));
1018 	if (init) {
1019 		debug("PAM: establishing credentials");
1020 		sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED);
1021 	} else {
1022 		debug("PAM: reinitializing credentials");
1023 		sshpam_err = pam_setcred(sshpam_handle, PAM_REINITIALIZE_CRED);
1024 	}
1025 	if (sshpam_err == PAM_SUCCESS) {
1026 		sshpam_cred_established = 1;
1027 		return;
1028 	}
1029 	if (sshpam_authenticated)
1030 		fatal("PAM: pam_setcred(): %s",
1031 		    pam_strerror(sshpam_handle, sshpam_err));
1032 	else
1033 		debug("PAM: pam_setcred(): %s",
1034 		    pam_strerror(sshpam_handle, sshpam_err));
1035 }
1036 
1037 static int
1038 sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
1039     struct pam_response **resp, void *data)
1040 {
1041 	char input[PAM_MAX_MSG_SIZE];
1042 	struct pam_response *reply;
1043 	int i;
1044 
1045 	debug3("PAM: %s called with %d messages", __func__, n);
1046 
1047 	*resp = NULL;
1048 
1049 	if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO))
1050 		return (PAM_CONV_ERR);
1051 
1052 	if ((reply = calloc(n, sizeof(*reply))) == NULL)
1053 		return (PAM_CONV_ERR);
1054 
1055 	for (i = 0; i < n; ++i) {
1056 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
1057 		case PAM_PROMPT_ECHO_OFF:
1058 			reply[i].resp =
1059 			    read_passphrase(PAM_MSG_MEMBER(msg, i, msg),
1060 			    RP_ALLOW_STDIN);
1061 			reply[i].resp_retcode = PAM_SUCCESS;
1062 			break;
1063 		case PAM_PROMPT_ECHO_ON:
1064 			fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg));
1065 			if (fgets(input, sizeof input, stdin) == NULL)
1066 				input[0] = '\0';
1067 			if ((reply[i].resp = strdup(input)) == NULL)
1068 				goto fail;
1069 			reply[i].resp_retcode = PAM_SUCCESS;
1070 			break;
1071 		case PAM_ERROR_MSG:
1072 		case PAM_TEXT_INFO:
1073 			fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg));
1074 			reply[i].resp_retcode = PAM_SUCCESS;
1075 			break;
1076 		default:
1077 			goto fail;
1078 		}
1079 	}
1080 	*resp = reply;
1081 	return (PAM_SUCCESS);
1082 
1083  fail:
1084 	for(i = 0; i < n; i++) {
1085 		free(reply[i].resp);
1086 	}
1087 	free(reply);
1088 	return (PAM_CONV_ERR);
1089 }
1090 
1091 static struct pam_conv tty_conv = { sshpam_tty_conv, NULL };
1092 
1093 /*
1094  * XXX this should be done in the authentication phase, but ssh1 doesn't
1095  * support that
1096  */
1097 void
1098 do_pam_chauthtok(void)
1099 {
1100 	if (use_privsep)
1101 		fatal("Password expired (unable to change with privsep)");
1102 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1103 	    (const void *)&tty_conv);
1104 	if (sshpam_err != PAM_SUCCESS)
1105 		fatal("PAM: failed to set PAM_CONV: %s",
1106 		    pam_strerror(sshpam_handle, sshpam_err));
1107 	debug("PAM: changing password");
1108 	sshpam_err = pam_chauthtok(sshpam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
1109 	if (sshpam_err != PAM_SUCCESS)
1110 		fatal("PAM: pam_chauthtok(): %s",
1111 		    pam_strerror(sshpam_handle, sshpam_err));
1112 }
1113 
1114 void
1115 do_pam_session(struct ssh *ssh)
1116 {
1117 	debug3("PAM: opening session");
1118 
1119 	expose_authinfo(__func__);
1120 
1121 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1122 	    (const void *)&store_conv);
1123 	if (sshpam_err != PAM_SUCCESS)
1124 		fatal("PAM: failed to set PAM_CONV: %s",
1125 		    pam_strerror(sshpam_handle, sshpam_err));
1126 	sshpam_err = pam_open_session(sshpam_handle, 0);
1127 	if (sshpam_err == PAM_SUCCESS)
1128 		sshpam_session_open = 1;
1129 	else {
1130 		sshpam_session_open = 0;
1131 		auth_restrict_session(ssh);
1132 		error("PAM: pam_open_session(): %s",
1133 		    pam_strerror(sshpam_handle, sshpam_err));
1134 	}
1135 
1136 }
1137 
1138 int
1139 is_pam_session_open(void)
1140 {
1141 	return sshpam_session_open;
1142 }
1143 
1144 /*
1145  * Set a PAM environment string. We need to do this so that the session
1146  * modules can handle things like Kerberos/GSI credentials that appear
1147  * during the ssh authentication process.
1148  */
1149 int
1150 do_pam_putenv(const char *name, char *value)
1151 {
1152 	int ret = 1;
1153 #ifdef HAVE_PAM_PUTENV
1154 	char *compound;
1155 	size_t len;
1156 
1157 	len = strlen(name) + strlen(value) + 2;
1158 	compound = xmalloc(len);
1159 
1160 	snprintf(compound, len, "%s=%s", name, value);
1161 	ret = pam_putenv(sshpam_handle, compound);
1162 	free(compound);
1163 #endif
1164 
1165 	return (ret);
1166 }
1167 
1168 char **
1169 fetch_pam_child_environment(void)
1170 {
1171 	return sshpam_env;
1172 }
1173 
1174 char **
1175 fetch_pam_environment(void)
1176 {
1177 	return (pam_getenvlist(sshpam_handle));
1178 }
1179 
1180 void
1181 free_pam_environment(char **env)
1182 {
1183 	char **envp;
1184 
1185 	if (env == NULL)
1186 		return;
1187 
1188 	for (envp = env; *envp; envp++)
1189 		free(*envp);
1190 	free(env);
1191 }
1192 
1193 /*
1194  * "Blind" conversation function for password authentication.  Assumes that
1195  * echo-off prompts are for the password and stores messages for later
1196  * display.
1197  */
1198 static int
1199 sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
1200     struct pam_response **resp, void *data)
1201 {
1202 	struct pam_response *reply;
1203 	int i;
1204 	size_t len;
1205 
1206 	debug3("PAM: %s called with %d messages", __func__, n);
1207 
1208 	*resp = NULL;
1209 
1210 	if (n <= 0 || n > PAM_MAX_NUM_MSG)
1211 		return (PAM_CONV_ERR);
1212 
1213 	if ((reply = calloc(n, sizeof(*reply))) == NULL)
1214 		return (PAM_CONV_ERR);
1215 
1216 	for (i = 0; i < n; ++i) {
1217 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
1218 		case PAM_PROMPT_ECHO_OFF:
1219 			if (sshpam_password == NULL)
1220 				goto fail;
1221 			if ((reply[i].resp = strdup(sshpam_password)) == NULL)
1222 				goto fail;
1223 			reply[i].resp_retcode = PAM_SUCCESS;
1224 			break;
1225 		case PAM_ERROR_MSG:
1226 		case PAM_TEXT_INFO:
1227 			len = strlen(PAM_MSG_MEMBER(msg, i, msg));
1228 			if (len > 0) {
1229 				buffer_append(&loginmsg,
1230 				    PAM_MSG_MEMBER(msg, i, msg), len);
1231 				buffer_append(&loginmsg, "\n", 1);
1232 			}
1233 			if ((reply[i].resp = strdup("")) == NULL)
1234 				goto fail;
1235 			reply[i].resp_retcode = PAM_SUCCESS;
1236 			break;
1237 		default:
1238 			goto fail;
1239 		}
1240 	}
1241 	*resp = reply;
1242 	return (PAM_SUCCESS);
1243 
1244  fail:
1245 	for(i = 0; i < n; i++) {
1246 		free(reply[i].resp);
1247 	}
1248 	free(reply);
1249 	return (PAM_CONV_ERR);
1250 }
1251 
1252 static struct pam_conv passwd_conv = { sshpam_passwd_conv, NULL };
1253 
1254 /*
1255  * Attempt password authentication via PAM
1256  */
1257 int
1258 sshpam_auth_passwd(Authctxt *authctxt, const char *password)
1259 {
1260 	int flags = (options.permit_empty_passwd == 0 ?
1261 	    PAM_DISALLOW_NULL_AUTHTOK : 0);
1262 	char *fake = NULL;
1263 
1264 	if (!options.use_pam || sshpam_handle == NULL)
1265 		fatal("PAM: %s called when PAM disabled or failed to "
1266 		    "initialise.", __func__);
1267 
1268 	sshpam_password = password;
1269 	sshpam_authctxt = authctxt;
1270 
1271 	/*
1272 	 * If the user logging in is invalid, or is root but is not permitted
1273 	 * by PermitRootLogin, use an invalid password to prevent leaking
1274 	 * information via timing (eg if the PAM config has a delay on fail).
1275 	 */
1276 	if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
1277 	    options.permit_root_login != PERMIT_YES))
1278 		sshpam_password = fake = fake_password(password);
1279 
1280 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1281 	    (const void *)&passwd_conv);
1282 	if (sshpam_err != PAM_SUCCESS)
1283 		fatal("PAM: %s: failed to set PAM_CONV: %s", __func__,
1284 		    pam_strerror(sshpam_handle, sshpam_err));
1285 
1286 	sshpam_err = pam_authenticate(sshpam_handle, flags);
1287 	sshpam_password = NULL;
1288 	free(fake);
1289 	if (sshpam_err == PAM_MAXTRIES)
1290 		sshpam_set_maxtries_reached(1);
1291 	if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
1292 		debug("PAM: password authentication accepted for %.100s",
1293 		    authctxt->user);
1294 		return 1;
1295 	} else {
1296 		debug("PAM: password authentication failed for %.100s: %s",
1297 		    authctxt->valid ? authctxt->user : "an illegal user",
1298 		    pam_strerror(sshpam_handle, sshpam_err));
1299 		return 0;
1300 	}
1301 }
1302 
1303 int
1304 sshpam_get_maxtries_reached(void)
1305 {
1306 	return sshpam_maxtries_reached;
1307 }
1308 
1309 void
1310 sshpam_set_maxtries_reached(int reached)
1311 {
1312 	if (reached == 0 || sshpam_maxtries_reached)
1313 		return;
1314 	sshpam_maxtries_reached = 1;
1315 	options.password_authentication = 0;
1316 	options.kbd_interactive_authentication = 0;
1317 	options.challenge_response_authentication = 0;
1318 }
1319 #endif /* USE_PAM */
1320