xref: /netbsd-src/crypto/external/bsd/openssh/dist/auth-pam.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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.15 2018/05/23 16:04:13 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 	pfilter_notify(1);
556 	buffer_free(&buffer);
557 	pthread_exit(NULL);
558 
559 	return (NULL); /* Avoid warning for non-pthread case */
560 }
561 
562 void
563 sshpam_thread_cleanup(void)
564 {
565 	struct pam_ctxt *ctxt = cleanup_ctxt;
566 
567 	debug3("PAM: %s entering", __func__);
568 	if (ctxt != NULL && ctxt->pam_thread != 0) {
569 		pthread_cancel(ctxt->pam_thread);
570 		pthread_join(ctxt->pam_thread, NULL);
571 		close(ctxt->pam_psock);
572 		close(ctxt->pam_csock);
573 		memset(ctxt, 0, sizeof(*ctxt));
574 		cleanup_ctxt = NULL;
575 	}
576 }
577 
578 static int
579 sshpam_null_conv(int n, sshpam_const struct pam_message **msg,
580     struct pam_response **resp, void *data)
581 {
582 	debug3("PAM: %s entering, %d messages", __func__, n);
583 	return (PAM_CONV_ERR);
584 }
585 
586 static struct pam_conv null_conv = { sshpam_null_conv, NULL };
587 
588 static int
589 sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
590     struct pam_response **resp, void *data)
591 {
592 	struct pam_response *reply;
593 	int i;
594 	size_t len;
595 
596 	debug3("PAM: %s called with %d messages", __func__, n);
597 	*resp = NULL;
598 
599 	if (n <= 0 || n > PAM_MAX_NUM_MSG)
600 		return (PAM_CONV_ERR);
601 
602 	if ((reply = calloc(n, sizeof(*reply))) == NULL)
603 		return (PAM_CONV_ERR);
604 
605 	for (i = 0; i < n; ++i) {
606 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
607 		case PAM_ERROR_MSG:
608 		case PAM_TEXT_INFO:
609 			len = strlen(PAM_MSG_MEMBER(msg, i, msg));
610 			buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len);
611 			buffer_append(&loginmsg, "\n", 1 );
612 			reply[i].resp_retcode = PAM_SUCCESS;
613 			break;
614 		default:
615 			goto fail;
616 		}
617 	}
618 	*resp = reply;
619 	return (PAM_SUCCESS);
620 
621  fail:
622 	for(i = 0; i < n; i++) {
623 		free(reply[i].resp);
624 	}
625 	free(reply);
626 	return (PAM_CONV_ERR);
627 }
628 
629 static struct pam_conv store_conv = { sshpam_store_conv, NULL };
630 
631 void
632 sshpam_cleanup(void)
633 {
634 	if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor()))
635 		return;
636 	debug("PAM: cleanup");
637 	pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
638 	if (sshpam_session_open) {
639 		debug("PAM: closing session");
640 		pam_close_session(sshpam_handle, PAM_SILENT);
641 		sshpam_session_open = 0;
642 	}
643 	if (sshpam_cred_established) {
644 		debug("PAM: deleting credentials");
645 		pam_setcred(sshpam_handle, PAM_DELETE_CRED);
646 		sshpam_cred_established = 0;
647 	}
648 	sshpam_authenticated = 0;
649 	pam_end(sshpam_handle, sshpam_err);
650 	sshpam_handle = NULL;
651 }
652 
653 static int
654 sshpam_init(Authctxt *authctxt)
655 {
656 	const char *pam_rhost, *pam_user, *user = authctxt->user;
657 	const char **ptr_pam_user = &pam_user;
658 	struct ssh *ssh = active_state; /* XXX */
659 
660 	if (sshpam_handle != NULL) {
661 		/* We already have a PAM context; check if the user matches */
662 		sshpam_err = pam_get_item(sshpam_handle,
663 		    PAM_USER, (sshpam_const void **)ptr_pam_user);
664 		if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
665 			return (0);
666 		pam_end(sshpam_handle, sshpam_err);
667 		sshpam_handle = NULL;
668 	}
669 	debug("PAM: initializing for \"%s\"", user);
670 	sshpam_err =
671 	    pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
672 	sshpam_authctxt = authctxt;
673 
674 	if (sshpam_err != PAM_SUCCESS) {
675 		pam_end(sshpam_handle, sshpam_err);
676 		sshpam_handle = NULL;
677 		return (-1);
678 	}
679 	pam_rhost = auth_get_canonical_hostname(ssh, options.use_dns);
680 	debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
681 	sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
682 	if (sshpam_err != PAM_SUCCESS) {
683 		pam_end(sshpam_handle, sshpam_err);
684 		sshpam_handle = NULL;
685 		return (-1);
686 	}
687 #ifdef PAM_TTY_KLUDGE
688 	/*
689 	 * Some silly PAM modules (e.g. pam_time) require a TTY to operate.
690 	 * sshd doesn't set the tty until too late in the auth process and
691 	 * may not even set one (for tty-less connections)
692 	 */
693 	debug("PAM: setting PAM_TTY to \"ssh\"");
694 	sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, "ssh");
695 	if (sshpam_err != PAM_SUCCESS) {
696 		pam_end(sshpam_handle, sshpam_err);
697 		sshpam_handle = NULL;
698 		return (-1);
699 	}
700 #endif
701 	return (0);
702 }
703 
704 static void *
705 sshpam_init_ctx(Authctxt *authctxt)
706 {
707 	struct pam_ctxt *ctxt;
708 	int socks[2];
709 
710 	debug3("PAM: %s entering", __func__);
711 	/*
712 	 * Refuse to start if we don't have PAM enabled or do_pam_account
713 	 * has previously failed.
714 	 */
715 	if (!options.use_pam || sshpam_account_status == 0)
716 		return NULL;
717 
718 	/* Initialize PAM */
719 	if (sshpam_init(authctxt) == -1) {
720 		error("PAM: initialization failed");
721 		return (NULL);
722 	}
723 
724 	ctxt = xcalloc(1, sizeof *ctxt);
725 
726 	/* Start the authentication thread */
727 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
728 		error("PAM: failed create sockets: %s", strerror(errno));
729 		free(ctxt);
730 		return (NULL);
731 	}
732 	ctxt->pam_psock = socks[0];
733 	ctxt->pam_csock = socks[1];
734 	if (pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt) == -1) {
735 		error("PAM: failed to start authentication thread: %s",
736 		    strerror(errno));
737 		close(socks[0]);
738 		close(socks[1]);
739 		free(ctxt);
740 		return (NULL);
741 	}
742 	cleanup_ctxt = ctxt;
743 	return (ctxt);
744 }
745 
746 static int
747 sshpam_query(void *ctx, char **name, char **info,
748     u_int *num, char ***prompts, u_int **echo_on)
749 {
750 	struct ssh *ssh = active_state; /* XXX */
751 	Buffer buffer;
752 	struct pam_ctxt *ctxt = ctx;
753 	size_t plen;
754 	u_char type;
755 	char *msg;
756 	size_t len, mlen;
757 
758 	debug3("PAM: %s entering", __func__);
759 	buffer_init(&buffer);
760 	*name = xstrdup("");
761 	*info = xstrdup("");
762 	*prompts = xmalloc(sizeof(char *));
763 	**prompts = NULL;
764 	plen = 0;
765 	*echo_on = xmalloc(sizeof(u_int));
766 	while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
767 		type = buffer_get_char(&buffer);
768 		msg = buffer_get_string(&buffer, NULL);
769 		mlen = strlen(msg);
770 		switch (type) {
771 		case PAM_PROMPT_ECHO_ON:
772 		case PAM_PROMPT_ECHO_OFF:
773 			*num = 1;
774 			len = plen + mlen + 1;
775 			**prompts = xreallocarray(**prompts, 1, len);
776 			strlcpy(**prompts + plen, msg, len - plen);
777 			plen += mlen;
778 			**echo_on = (type == PAM_PROMPT_ECHO_ON);
779 			free(msg);
780 			return (0);
781 		case PAM_ERROR_MSG:
782 		case PAM_TEXT_INFO:
783 			/* accumulate messages */
784 			len = plen + mlen + 2;
785 			**prompts = xreallocarray(**prompts, 1, len);
786 			strlcpy(**prompts + plen, msg, len - plen);
787 			plen += mlen;
788 			strlcat(**prompts + plen, "\n", len - plen);
789 			plen++;
790 			free(msg);
791 			break;
792 		case PAM_ACCT_EXPIRED:
793 		case PAM_MAXTRIES:
794 			if (type == PAM_ACCT_EXPIRED)
795 				sshpam_account_status = 0;
796 			if (type == PAM_MAXTRIES)
797 				sshpam_set_maxtries_reached(1);
798 			/* FALLTHROUGH */
799 		case PAM_AUTH_ERR:
800 			debug3("PAM: %s", pam_strerror(sshpam_handle, type));
801 			if (**prompts != NULL && strlen(**prompts) != 0) {
802 				*info = **prompts;
803 				**prompts = NULL;
804 				*num = 0;
805 				**echo_on = 0;
806 				ctxt->pam_done = -1;
807 				free(msg);
808 				return 0;
809 			}
810 			/* FALLTHROUGH */
811 		case PAM_SUCCESS:
812 			if (**prompts != NULL) {
813 				/* drain any accumulated messages */
814 				debug("PAM: %s", **prompts);
815 				buffer_append(&loginmsg, **prompts,
816 				    strlen(**prompts));
817 				free(**prompts);
818 				**prompts = NULL;
819 			}
820 			if (type == PAM_SUCCESS) {
821 				if (!sshpam_authctxt->valid ||
822 				    (sshpam_authctxt->pw->pw_uid == 0 &&
823 				    options.permit_root_login != PERMIT_YES))
824 					fatal("Internal error: PAM auth "
825 					    "succeeded when it should have "
826 					    "failed");
827 				import_environments(&buffer);
828 				*num = 0;
829 				**echo_on = 0;
830 				ctxt->pam_done = 1;
831 				free(msg);
832 				return (0);
833 			}
834 			pfilter_notify(1);
835 			error("PAM: %s for %s%.100s from %.100s", msg,
836 			    sshpam_authctxt->valid ? "" : "illegal user ",
837 			    sshpam_authctxt->user,
838 			    auth_get_canonical_hostname(ssh, options.use_dns));
839 			/* FALLTHROUGH */
840 		default:
841 			*num = 0;
842 			**echo_on = 0;
843 			free(msg);
844 			ctxt->pam_done = -1;
845 			return (-1);
846 		}
847 	}
848 	return (-1);
849 }
850 
851 /*
852  * Returns a junk password of identical length to that the user supplied.
853  * Used to mitigate timing attacks against crypt(3)/PAM stacks that
854  * vary processing time in proportion to password length.
855  */
856 static char *
857 fake_password(const char *wire_password)
858 {
859 	const char junk[] = "\b\n\r\177INCORRECT";
860 	char *ret = NULL;
861 	size_t i, l = wire_password != NULL ? strlen(wire_password) : 0;
862 
863 	if (l >= INT_MAX)
864 		fatal("%s: password length too long: %zu", __func__, l);
865 
866 	ret = malloc(l + 1);
867 	if (ret == NULL)
868 		return NULL;
869 	for (i = 0; i < l; i++)
870 		ret[i] = junk[i % (sizeof(junk) - 1)];
871 	ret[i] = '\0';
872 	return ret;
873 }
874 
875 /* XXX - see also comment in auth-chall.c:verify_response */
876 static int
877 sshpam_respond(void *ctx, u_int num, char **resp)
878 {
879 	Buffer buffer;
880 	struct pam_ctxt *ctxt = ctx;
881 	char *fake;
882 
883 	debug2("PAM: %s entering, %u responses", __func__, num);
884 	switch (ctxt->pam_done) {
885 	case 1:
886 		sshpam_authenticated = 1;
887 		return (0);
888 	case 0:
889 		break;
890 	default:
891 		return (-1);
892 	}
893 	if (num != 1) {
894 		error("PAM: expected one response, got %u", num);
895 		return (-1);
896 	}
897 	buffer_init(&buffer);
898 	if (sshpam_authctxt->valid &&
899 	    (sshpam_authctxt->pw->pw_uid != 0 ||
900 	    options.permit_root_login == PERMIT_YES))
901 		buffer_put_cstring(&buffer, *resp);
902 	else {
903 		fake = fake_password(*resp);
904 		buffer_put_cstring(&buffer, fake);
905 		free(fake);
906 	}
907 	if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
908 		buffer_free(&buffer);
909 		return (-1);
910 	}
911 	buffer_free(&buffer);
912 	return (1);
913 }
914 
915 static void
916 sshpam_free_ctx(void *ctxtp)
917 {
918 	struct pam_ctxt *ctxt = ctxtp;
919 
920 	debug3("PAM: %s entering", __func__);
921 	sshpam_thread_cleanup();
922 	free(ctxt);
923 	/*
924 	 * We don't call sshpam_cleanup() here because we may need the PAM
925 	 * handle at a later stage, e.g. when setting up a session.  It's
926 	 * still on the cleanup list, so pam_end() *will* be called before
927 	 * the server process terminates.
928 	 */
929 }
930 
931 KbdintDevice sshpam_device = {
932 	"pam",
933 	sshpam_init_ctx,
934 	sshpam_query,
935 	sshpam_respond,
936 	sshpam_free_ctx
937 };
938 
939 KbdintDevice mm_sshpam_device = {
940 	"pam",
941 	mm_sshpam_init_ctx,
942 	mm_sshpam_query,
943 	mm_sshpam_respond,
944 	mm_sshpam_free_ctx
945 };
946 
947 /*
948  * This replaces auth-pam.c
949  */
950 void
951 start_pam(Authctxt *authctxt)
952 {
953 	if (!options.use_pam)
954 		fatal("PAM: initialisation requested when UsePAM=no");
955 
956 	if (sshpam_init(authctxt) == -1)
957 		fatal("PAM: initialisation failed");
958 }
959 
960 void
961 finish_pam(void)
962 {
963 	sshpam_cleanup();
964 }
965 
966 static void
967 expose_authinfo(const char *caller)
968 {
969 	char *auth_info;
970 
971 	/*
972 	 * Expose authentication information to PAM.
973 	 * The enviornment variable is versioned. Please increment the
974 	 * version suffix if the format of session_info changes.
975 	 */
976 	if (sshpam_authctxt->session_info == NULL)
977 		auth_info = xstrdup("");
978 	else if ((auth_info = sshbuf_dup_string(
979 	    sshpam_authctxt->session_info)) == NULL)
980 		fatal("%s: sshbuf_dup_string failed", __func__);
981 
982 	debug2("%s: auth information in SSH_AUTH_INFO_0", caller);
983 	do_pam_putenv("SSH_AUTH_INFO_0", auth_info);
984 	free(auth_info);
985 }
986 
987 u_int
988 do_pam_account(void)
989 {
990 	debug("%s: called", __func__);
991 	if (sshpam_account_status != -1)
992 		return (sshpam_account_status);
993 
994 	expose_authinfo(__func__);
995 
996 	sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
997 	debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
998 	    pam_strerror(sshpam_handle, sshpam_err));
999 
1000 	if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
1001 		sshpam_account_status = 0;
1002 		return (sshpam_account_status);
1003 	}
1004 
1005 	if (sshpam_err == PAM_NEW_AUTHTOK_REQD)
1006 		sshpam_password_change_required(1);
1007 
1008 	sshpam_account_status = 1;
1009 	return (sshpam_account_status);
1010 }
1011 
1012 void
1013 do_pam_setcred(int init)
1014 {
1015 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1016 	    (const void *)&store_conv);
1017 	if (sshpam_err != PAM_SUCCESS)
1018 		fatal("PAM: failed to set PAM_CONV: %s",
1019 		    pam_strerror(sshpam_handle, sshpam_err));
1020 	if (init) {
1021 		debug("PAM: establishing credentials");
1022 		sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED);
1023 	} else {
1024 		debug("PAM: reinitializing credentials");
1025 		sshpam_err = pam_setcred(sshpam_handle, PAM_REINITIALIZE_CRED);
1026 	}
1027 	if (sshpam_err == PAM_SUCCESS) {
1028 		sshpam_cred_established = 1;
1029 		return;
1030 	}
1031 	if (sshpam_authenticated)
1032 		fatal("PAM: pam_setcred(): %s",
1033 		    pam_strerror(sshpam_handle, sshpam_err));
1034 	else
1035 		debug("PAM: pam_setcred(): %s",
1036 		    pam_strerror(sshpam_handle, sshpam_err));
1037 }
1038 
1039 static int
1040 sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
1041     struct pam_response **resp, void *data)
1042 {
1043 	char input[PAM_MAX_MSG_SIZE];
1044 	struct pam_response *reply;
1045 	int i;
1046 
1047 	debug3("PAM: %s called with %d messages", __func__, n);
1048 
1049 	*resp = NULL;
1050 
1051 	if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO))
1052 		return (PAM_CONV_ERR);
1053 
1054 	if ((reply = calloc(n, sizeof(*reply))) == NULL)
1055 		return (PAM_CONV_ERR);
1056 
1057 	for (i = 0; i < n; ++i) {
1058 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
1059 		case PAM_PROMPT_ECHO_OFF:
1060 			reply[i].resp =
1061 			    read_passphrase(PAM_MSG_MEMBER(msg, i, msg),
1062 			    RP_ALLOW_STDIN);
1063 			reply[i].resp_retcode = PAM_SUCCESS;
1064 			break;
1065 		case PAM_PROMPT_ECHO_ON:
1066 			fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg));
1067 			if (fgets(input, sizeof input, stdin) == NULL)
1068 				input[0] = '\0';
1069 			if ((reply[i].resp = strdup(input)) == NULL)
1070 				goto fail;
1071 			reply[i].resp_retcode = PAM_SUCCESS;
1072 			break;
1073 		case PAM_ERROR_MSG:
1074 		case PAM_TEXT_INFO:
1075 			fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg));
1076 			reply[i].resp_retcode = PAM_SUCCESS;
1077 			break;
1078 		default:
1079 			goto fail;
1080 		}
1081 	}
1082 	*resp = reply;
1083 	return (PAM_SUCCESS);
1084 
1085  fail:
1086 	for(i = 0; i < n; i++) {
1087 		free(reply[i].resp);
1088 	}
1089 	free(reply);
1090 	return (PAM_CONV_ERR);
1091 }
1092 
1093 static struct pam_conv tty_conv = { sshpam_tty_conv, NULL };
1094 
1095 /*
1096  * XXX this should be done in the authentication phase, but ssh1 doesn't
1097  * support that
1098  */
1099 void
1100 do_pam_chauthtok(void)
1101 {
1102 	if (use_privsep)
1103 		fatal("Password expired (unable to change with privsep)");
1104 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1105 	    (const void *)&tty_conv);
1106 	if (sshpam_err != PAM_SUCCESS)
1107 		fatal("PAM: failed to set PAM_CONV: %s",
1108 		    pam_strerror(sshpam_handle, sshpam_err));
1109 	debug("PAM: changing password");
1110 	sshpam_err = pam_chauthtok(sshpam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
1111 	if (sshpam_err != PAM_SUCCESS)
1112 		fatal("PAM: pam_chauthtok(): %s",
1113 		    pam_strerror(sshpam_handle, sshpam_err));
1114 }
1115 
1116 void
1117 do_pam_session(struct ssh *ssh)
1118 {
1119 	debug3("PAM: opening session");
1120 
1121 	expose_authinfo(__func__);
1122 
1123 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1124 	    (const void *)&store_conv);
1125 	if (sshpam_err != PAM_SUCCESS)
1126 		fatal("PAM: failed to set PAM_CONV: %s",
1127 		    pam_strerror(sshpam_handle, sshpam_err));
1128 	sshpam_err = pam_open_session(sshpam_handle, 0);
1129 	if (sshpam_err == PAM_SUCCESS)
1130 		sshpam_session_open = 1;
1131 	else {
1132 		sshpam_session_open = 0;
1133 		auth_restrict_session(ssh);
1134 		error("PAM: pam_open_session(): %s",
1135 		    pam_strerror(sshpam_handle, sshpam_err));
1136 	}
1137 
1138 }
1139 
1140 int
1141 is_pam_session_open(void)
1142 {
1143 	return sshpam_session_open;
1144 }
1145 
1146 /*
1147  * Set a PAM environment string. We need to do this so that the session
1148  * modules can handle things like Kerberos/GSI credentials that appear
1149  * during the ssh authentication process.
1150  */
1151 int
1152 do_pam_putenv(const char *name, char *value)
1153 {
1154 	int ret = 1;
1155 #ifdef HAVE_PAM_PUTENV
1156 	char *compound;
1157 	size_t len;
1158 
1159 	len = strlen(name) + strlen(value) + 2;
1160 	compound = xmalloc(len);
1161 
1162 	snprintf(compound, len, "%s=%s", name, value);
1163 	ret = pam_putenv(sshpam_handle, compound);
1164 	free(compound);
1165 #endif
1166 
1167 	return (ret);
1168 }
1169 
1170 char **
1171 fetch_pam_child_environment(void)
1172 {
1173 	return sshpam_env;
1174 }
1175 
1176 char **
1177 fetch_pam_environment(void)
1178 {
1179 	return (pam_getenvlist(sshpam_handle));
1180 }
1181 
1182 void
1183 free_pam_environment(char **env)
1184 {
1185 	char **envp;
1186 
1187 	if (env == NULL)
1188 		return;
1189 
1190 	for (envp = env; *envp; envp++)
1191 		free(*envp);
1192 	free(env);
1193 }
1194 
1195 /*
1196  * "Blind" conversation function for password authentication.  Assumes that
1197  * echo-off prompts are for the password and stores messages for later
1198  * display.
1199  */
1200 static int
1201 sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
1202     struct pam_response **resp, void *data)
1203 {
1204 	struct pam_response *reply;
1205 	int i;
1206 	size_t len;
1207 
1208 	debug3("PAM: %s called with %d messages", __func__, n);
1209 
1210 	*resp = NULL;
1211 
1212 	if (n <= 0 || n > PAM_MAX_NUM_MSG)
1213 		return (PAM_CONV_ERR);
1214 
1215 	if ((reply = calloc(n, sizeof(*reply))) == NULL)
1216 		return (PAM_CONV_ERR);
1217 
1218 	for (i = 0; i < n; ++i) {
1219 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
1220 		case PAM_PROMPT_ECHO_OFF:
1221 			if (sshpam_password == NULL)
1222 				goto fail;
1223 			if ((reply[i].resp = strdup(sshpam_password)) == NULL)
1224 				goto fail;
1225 			reply[i].resp_retcode = PAM_SUCCESS;
1226 			break;
1227 		case PAM_ERROR_MSG:
1228 		case PAM_TEXT_INFO:
1229 			len = strlen(PAM_MSG_MEMBER(msg, i, msg));
1230 			if (len > 0) {
1231 				buffer_append(&loginmsg,
1232 				    PAM_MSG_MEMBER(msg, i, msg), len);
1233 				buffer_append(&loginmsg, "\n", 1);
1234 			}
1235 			if ((reply[i].resp = strdup("")) == NULL)
1236 				goto fail;
1237 			reply[i].resp_retcode = PAM_SUCCESS;
1238 			break;
1239 		default:
1240 			goto fail;
1241 		}
1242 	}
1243 	*resp = reply;
1244 	return (PAM_SUCCESS);
1245 
1246  fail:
1247 	for(i = 0; i < n; i++) {
1248 		free(reply[i].resp);
1249 	}
1250 	free(reply);
1251 	return (PAM_CONV_ERR);
1252 }
1253 
1254 static struct pam_conv passwd_conv = { sshpam_passwd_conv, NULL };
1255 
1256 /*
1257  * Attempt password authentication via PAM
1258  */
1259 int
1260 sshpam_auth_passwd(Authctxt *authctxt, const char *password)
1261 {
1262 	int flags = (options.permit_empty_passwd == 0 ?
1263 	    PAM_DISALLOW_NULL_AUTHTOK : 0);
1264 	char *fake = NULL;
1265 
1266 	if (!options.use_pam || sshpam_handle == NULL)
1267 		fatal("PAM: %s called when PAM disabled or failed to "
1268 		    "initialise.", __func__);
1269 
1270 	sshpam_password = password;
1271 	sshpam_authctxt = authctxt;
1272 
1273 	/*
1274 	 * If the user logging in is invalid, or is root but is not permitted
1275 	 * by PermitRootLogin, use an invalid password to prevent leaking
1276 	 * information via timing (eg if the PAM config has a delay on fail).
1277 	 */
1278 	if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
1279 	    options.permit_root_login != PERMIT_YES))
1280 		sshpam_password = fake = fake_password(password);
1281 
1282 	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1283 	    (const void *)&passwd_conv);
1284 	if (sshpam_err != PAM_SUCCESS)
1285 		fatal("PAM: %s: failed to set PAM_CONV: %s", __func__,
1286 		    pam_strerror(sshpam_handle, sshpam_err));
1287 
1288 	sshpam_err = pam_authenticate(sshpam_handle, flags);
1289 	sshpam_password = NULL;
1290 	free(fake);
1291 	if (sshpam_err == PAM_MAXTRIES)
1292 		sshpam_set_maxtries_reached(1);
1293 	if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
1294 		debug("PAM: password authentication accepted for %.100s",
1295 		    authctxt->user);
1296 		return 1;
1297 	} else {
1298 		debug("PAM: password authentication failed for %.100s: %s",
1299 		    authctxt->valid ? authctxt->user : "an illegal user",
1300 		    pam_strerror(sshpam_handle, sshpam_err));
1301 		return 0;
1302 	}
1303 }
1304 
1305 int
1306 sshpam_get_maxtries_reached(void)
1307 {
1308 	return sshpam_maxtries_reached;
1309 }
1310 
1311 void
1312 sshpam_set_maxtries_reached(int reached)
1313 {
1314 	if (reached == 0 || sshpam_maxtries_reached)
1315 		return;
1316 	sshpam_maxtries_reached = 1;
1317 	options.password_authentication = 0;
1318 	options.kbd_interactive_authentication = 0;
1319 	options.challenge_response_authentication = 0;
1320 }
1321 #endif /* USE_PAM */
1322