11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*-
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2002 Networks Associates Technology, Inc.
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * All rights reserved.
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This software was developed for the FreeBSD Project by ThinkSec AS and
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NAI Labs, the Security Research Division of Network Associates, Inc.
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DARPA CHATS research program.
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * SUCH DAMAGE.
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2003,2004 Damien Miller <djm@mindrot.org>
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2003,2004 Darren Tucker <dtucker@zip.com.au>
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies.
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/stat.h>
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/wait.h>
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h>
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PAM
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_SECURITY_PAM_APPL_H)
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <security/pam_appl.h>
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#elif defined (HAVE_PAM_PAM_APPL_H)
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pam/pam_appl.h>
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef PAM_SUN_CODEBASE
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define sshpam_const		/* Solaris, HP-UX, AIX */
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define sshpam_const	const	/* LinuxPAM, OpenPAM */
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef PAM_SUN_CODEBASE
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member)
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member)
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "hostfile.h"
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth.h"
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth-pam.h"
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "canohost.h"
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "msg.h"
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "servconf.h"
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth-options.h"
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-gss.h"
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "monitor_wrap.h"
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern ServerOptions options;
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern Buffer loginmsg;
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int compat20;
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern u_int utmp_len;
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* so we don't silently change behaviour */
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_POSIX_THREADS
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# error "USE_POSIX_THREADS replaced by UNSUPPORTED_POSIX_THREADS_HACK"
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Formerly known as USE_POSIX_THREADS, using this is completely unsupported
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * and generally a bad idea.  Use at own risk and do not expect support if
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * this breaks.
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef UNSUPPORTED_POSIX_THREADS_HACK
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pthread.h>
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Avoid namespace clash when *not* using pthreads for systems *with*
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * pthreads, which unconditionally define pthread_t via sys/types.h
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (e.g. Linux)
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef pthread_t sp_pthread_t;
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef pid_t sp_pthread_t;
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct pam_ctxt {
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sp_pthread_t	 pam_thread;
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int		 pam_psock;
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int		 pam_csock;
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int		 pam_done;
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void sshpam_free_ctx(void *);
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct pam_ctxt *cleanup_ctxt;
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef UNSUPPORTED_POSIX_THREADS_HACK
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Simulate threads with processes.
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sshpam_thread_status = -1;
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic mysig_t sshpam_oldsig;
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_sigchld_handler(int sig)
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGCHLD, SIG_DFL);
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cleanup_ctxt == NULL)
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;	/* handler called after PAM cleanup, shouldn't happen */
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    <= 0) {
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* PAM thread has not exitted, privsep slave must have */
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		kill(cleanup_ctxt->pam_thread, SIGTERM);
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0)
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    <= 0)
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return; /* could not wait */
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (WIFSIGNALED(sshpam_thread_status) &&
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    WTERMSIG(sshpam_thread_status) == SIGTERM)
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;	/* terminated by pthread_cancel */
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!WIFEXITED(sshpam_thread_status))
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sigdie("PAM: authentication thread exited unexpectedly");
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (WEXITSTATUS(sshpam_thread_status) != 0)
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sigdie("PAM: authentication thread exited uncleanly");
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpthread_exit(void *value)
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	_exit(0);
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpthread_create(sp_pthread_t *thread, const void *attr,
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    void *(*thread_start)(void *), void *arg)
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid_t pid;
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_ctxt *ctx = arg;
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_thread_status = -1;
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch ((pid = fork())) {
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case -1:
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("fork(): %s", strerror(errno));
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 0:
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ctx->pam_psock);
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ctx->pam_psock = -1;
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		thread_start(arg);
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		_exit(1);
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*thread = pid;
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ctx->pam_csock);
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ctx->pam_csock = -1;
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (0);
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpthread_cancel(sp_pthread_t thread)
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGCHLD, sshpam_oldsig);
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (kill(thread, SIGTERM));
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpthread_join(sp_pthread_t thread, void **value)
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int status;
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_thread_status != -1)
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (sshpam_thread_status);
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGCHLD, sshpam_oldsig);
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	waitpid(thread, &status, 0);
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (status);
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic pam_handle_t *sshpam_handle = NULL;
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sshpam_err = 0;
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sshpam_authenticated = 0;
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sshpam_session_open = 0;
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sshpam_cred_established = 0;
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sshpam_account_status = -1;
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char **sshpam_env = NULL;
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Authctxt *sshpam_authctxt = NULL;
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic const char *sshpam_password = NULL;
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char badpw[] = "\b\n\r\177INCORRECT";
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Some PAM implementations don't implement this */
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef HAVE_PAM_GETENVLIST
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char **
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpam_getenvlist(pam_handle_t *pamh)
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * XXX - If necessary, we can still support envrionment passing
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * for platforms without pam_getenvlist by searching for known
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * env vars (e.g. KRB5CCNAME) from the PAM environment.
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 return NULL;
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Some platforms, notably Solaris, do not enforce password complexity
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * rules during pam_chauthtok() if the real uid of the calling process
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * is 0, on the assumption that it's being called by "passwd" run by root.
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This wraps pam_chauthtok and sets/restore the real uid so PAM will do
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the right thing.
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef SSHPAM_CHAUTHTOK_NEEDS_RUID
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_chauthtok_ruid(pam_handle_t *pamh, int flags)
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int result;
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_authctxt == NULL)
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: sshpam_authctxt not initialized");
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1)
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: setreuid failed: %s", __func__, strerror(errno));
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	result = pam_chauthtok(pamh, flags);
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setreuid(0, -1) == -1)
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: setreuid failed: %s", __func__, strerror(errno));
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return result;
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define pam_chauthtok(a,b)	(sshpam_chauthtok_ruid((a), (b)))
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_password_change_required(int reqd)
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s %d", __func__, reqd);
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_authctxt == NULL)
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: PAM authctxt not initialized", __func__);
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_authctxt->force_pwchange = reqd;
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (reqd) {
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		no_port_forwarding_flag |= 2;
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		no_agent_forwarding_flag |= 2;
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		no_x11_forwarding_flag |= 2;
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		no_port_forwarding_flag &= ~2;
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		no_agent_forwarding_flag &= ~2;
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		no_x11_forwarding_flag &= ~2;
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Import regular and PAM environment from subprocess */
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodimport_environments(Buffer *b)
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *env;
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, num_env;
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int err;
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s entering", __func__);
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef UNSUPPORTED_POSIX_THREADS_HACK
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Import variables set by do_pam_account */
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_account_status = buffer_get_int(b);
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_password_change_required(buffer_get_int(b));
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Import environment from subprocess */
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	num_env = buffer_get_int(b);
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (num_env > 1024)
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: received %u environment variables, expected <= 1024",
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, num_env);
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env));
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: num env strings %d", num_env);
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; i < num_env; i++)
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_env[i] = buffer_get_string(b, NULL);
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_env[num_env] = NULL;
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Import PAM environment from subprocess */
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	num_env = buffer_get_int(b);
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("PAM: num PAM env strings %d", num_env);
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; i < num_env; i++) {
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		env = buffer_get_string(b, NULL);
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PAM_PUTENV
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Errors are not fatal here */
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((err = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) {
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("PAM: pam_putenv: %s",
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    pam_strerror(sshpam_handle, sshpam_err));
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Conversation function for authentication thread.
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    struct pam_response **resp, void *data)
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer buffer;
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_ctxt *ctxt;
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_response *reply;
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s entering, %d messages", __func__, n);
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*resp = NULL;
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (data == NULL) {
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("PAM: conversation function passed a null context");
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ctxt = data;
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n <= 0 || n > PAM_MAX_NUM_MSG)
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((reply = calloc(n, sizeof(*reply))) == NULL)
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&buffer);
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < n; ++i) {
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_PROMPT_ECHO_OFF:
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_cstring(&buffer,
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_MSG_MEMBER(msg, i, msg));
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ssh_msg_send(ctxt->pam_csock,
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1)
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (buffer_get_char(&buffer) != PAM_AUTHTOK)
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp = buffer_get_string(&buffer, NULL);
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_PROMPT_ECHO_ON:
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_cstring(&buffer,
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_MSG_MEMBER(msg, i, msg));
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ssh_msg_send(ctxt->pam_csock,
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1)
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (buffer_get_char(&buffer) != PAM_AUTHTOK)
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp = buffer_get_string(&buffer, NULL);
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_ERROR_MSG:
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_cstring(&buffer,
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_MSG_MEMBER(msg, i, msg));
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ssh_msg_send(ctxt->pam_csock,
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_TEXT_INFO:
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_cstring(&buffer,
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_MSG_MEMBER(msg, i, msg));
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ssh_msg_send(ctxt->pam_csock,
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto fail;
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&buffer);
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&buffer);
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*resp = reply;
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_SUCCESS);
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fail:
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; i < n; i++) {
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (reply[i].resp != NULL)
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(reply[i].resp);
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(reply);
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&buffer);
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_CONV_ERR);
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Authentication thread.
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void *
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_thread(void *ctxtp)
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_ctxt *ctxt = ctxtp;
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer buffer;
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_conv sshpam_conv;
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int flags = (options.permit_empty_passwd == 0 ?
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    PAM_DISALLOW_NULL_AUTHTOK : 0);
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef UNSUPPORTED_POSIX_THREADS_HACK
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	extern char **environ;
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char **env_from_pam;
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *pam_user;
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char **ptr_pam_user = &pam_user;
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *tz = getenv("TZ");
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pam_get_item(sshpam_handle, PAM_USER,
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (sshpam_const void **)ptr_pam_user);
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	environ[0] = NULL;
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (tz != NULL)
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (setenv("TZ", tz, 1) == -1)
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("PAM: could not set TZ environment: %s",
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    strerror(errno));
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_authctxt != NULL) {
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		setproctitle("%s [pam]",
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    sshpam_authctxt->valid ? pam_user : "unknown");
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_conv.conv = sshpam_thread_conv;
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_conv.appdata_ptr = ctxt;
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_authctxt == NULL)
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: PAM authctxt not initialized", __func__);
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&buffer);
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (const void *)&sshpam_conv);
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS)
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto auth_fail;
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_authenticate(sshpam_handle, flags);
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS)
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto auth_fail;
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20) {
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!do_pam_account()) {
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sshpam_err = PAM_ACCT_EXPIRED;
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto auth_fail;
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (sshpam_authctxt->force_pwchange) {
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sshpam_err = pam_chauthtok(sshpam_handle,
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    PAM_CHANGE_EXPIRED_AUTHTOK);
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (sshpam_err != PAM_SUCCESS)
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto auth_fail;
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sshpam_password_change_required(0);
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&buffer, "OK");
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef UNSUPPORTED_POSIX_THREADS_HACK
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Export variables set by do_pam_account */
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&buffer, sshpam_account_status);
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&buffer, sshpam_authctxt->force_pwchange);
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Export any environment strings set in child */
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; environ[i] != NULL; i++)
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		; /* Count */
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&buffer, i);
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; environ[i] != NULL; i++)
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&buffer, environ[i]);
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Export any environment strings set by PAM in child */
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	env_from_pam = pam_getenvlist(sshpam_handle);
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		; /* Count */
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&buffer, i);
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&buffer, env_from_pam[i]);
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* UNSUPPORTED_POSIX_THREADS_HACK */
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* XXX - can't do much about an error here */
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer);
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&buffer);
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pthread_exit(NULL);
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood auth_fail:
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&buffer,
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pam_strerror(sshpam_handle, sshpam_err));
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* XXX - can't do much about an error here */
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err == PAM_ACCT_EXPIRED)
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer);
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&buffer);
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pthread_exit(NULL);
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (NULL); /* Avoid warning for non-pthread case */
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_thread_cleanup(void)
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_ctxt *ctxt = cleanup_ctxt;
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s entering", __func__);
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ctxt != NULL && ctxt->pam_thread != 0) {
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pthread_cancel(ctxt->pam_thread);
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pthread_join(ctxt->pam_thread, NULL);
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ctxt->pam_psock);
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ctxt->pam_csock);
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(ctxt, 0, sizeof(*ctxt));
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_ctxt = NULL;
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_null_conv(int n, sshpam_const struct pam_message **msg,
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    struct pam_response **resp, void *data)
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s entering, %d messages", __func__, n);
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_CONV_ERR);
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct pam_conv null_conv = { sshpam_null_conv, NULL };
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_store_conv(int n, sshpam_const struct pam_message **msg,
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    struct pam_response **resp, void *data)
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_response *reply;
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t len;
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s called with %d messages", __func__, n);
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*resp = NULL;
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n <= 0 || n > PAM_MAX_NUM_MSG)
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((reply = calloc(n, sizeof(*reply))) == NULL)
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < n; ++i) {
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_ERROR_MSG:
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_TEXT_INFO:
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			len = strlen(PAM_MSG_MEMBER(msg, i, msg));
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len);
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_append(&loginmsg, "\n", 1 );
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp_retcode = PAM_SUCCESS;
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto fail;
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*resp = reply;
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_SUCCESS);
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fail:
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; i < n; i++) {
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (reply[i].resp != NULL)
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(reply[i].resp);
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(reply);
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_CONV_ERR);
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct pam_conv store_conv = { sshpam_store_conv, NULL };
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_cleanup(void)
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor()))
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("PAM: cleanup");
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_session_open) {
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("PAM: closing session");
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pam_close_session(sshpam_handle, PAM_SILENT);
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_session_open = 0;
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_cred_established) {
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("PAM: deleting credentials");
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pam_setcred(sshpam_handle, PAM_DELETE_CRED);
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_cred_established = 0;
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_authenticated = 0;
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pam_end(sshpam_handle, sshpam_err);
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_handle = NULL;
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_init(Authctxt *authctxt)
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	extern char *__progname;
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *pam_rhost, *pam_user, *user = authctxt->user;
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char **ptr_pam_user = &pam_user;
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_handle != NULL) {
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* We already have a PAM context; check if the user matches */
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_err = pam_get_item(sshpam_handle,
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    PAM_USER, (sshpam_const void **)ptr_pam_user);
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (0);
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pam_end(sshpam_handle, sshpam_err);
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_handle = NULL;
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("PAM: initializing for \"%s\"", user);
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err =
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_authctxt = authctxt;
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS) {
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pam_end(sshpam_handle, sshpam_err);
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_handle = NULL;
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pam_rhost = get_remote_name_or_ip(utmp_len, options.use_dns);
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS) {
6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pam_end(sshpam_handle, sshpam_err);
6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_handle = NULL;
6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef PAM_TTY_KLUDGE
6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Some silly PAM modules (e.g. pam_time) require a TTY to operate.
6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * sshd doesn't set the tty until too late in the auth process and
6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * may not even set one (for tty-less connections)
6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("PAM: setting PAM_TTY to \"ssh\"");
6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, "ssh");
6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS) {
6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pam_end(sshpam_handle, sshpam_err);
6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_handle = NULL;
6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (0);
6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void *
6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_init_ctx(Authctxt *authctxt)
6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_ctxt *ctxt;
6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int socks[2];
6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s entering", __func__);
6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Refuse to start if we don't have PAM enabled or do_pam_account
6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * has previously failed.
6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.use_pam || sshpam_account_status == 0)
6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Initialize PAM */
6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_init(authctxt) == -1) {
6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("PAM: initialization failed");
6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (NULL);
6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ctxt = xcalloc(1, sizeof *ctxt);
6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Start the authentication thread */
6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("PAM: failed create sockets: %s", strerror(errno));
6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(ctxt);
6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (NULL);
6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ctxt->pam_psock = socks[0];
7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ctxt->pam_csock = socks[1];
7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt) == -1) {
7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("PAM: failed to start authentication thread: %s",
7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strerror(errno));
7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(socks[0]);
7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(socks[1]);
7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(ctxt);
7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (NULL);
7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cleanup_ctxt = ctxt;
7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (ctxt);
7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_query(void *ctx, char **name, char **info,
7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    u_int *num, char ***prompts, u_int **echo_on)
7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer buffer;
7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_ctxt *ctxt = ctx;
7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t plen;
7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char type;
7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *msg;
7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t len, mlen;
7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s entering", __func__);
7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&buffer);
7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*name = xstrdup("");
7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*info = xstrdup("");
7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*prompts = xmalloc(sizeof(char *));
7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	**prompts = NULL;
7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	plen = 0;
7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*echo_on = xmalloc(sizeof(u_int));
7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		type = buffer_get_char(&buffer);
7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		msg = buffer_get_string(&buffer, NULL);
7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		mlen = strlen(msg);
7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (type) {
7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_PROMPT_ECHO_ON:
7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_PROMPT_ECHO_OFF:
7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*num = 1;
7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			len = plen + mlen + 1;
7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			**prompts = xrealloc(**prompts, 1, len);
7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcpy(**prompts + plen, msg, len - plen);
7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			plen += mlen;
7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			**echo_on = (type == PAM_PROMPT_ECHO_ON);
7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(msg);
7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (0);
7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_ERROR_MSG:
7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_TEXT_INFO:
7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* accumulate messages */
7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			len = plen + mlen + 2;
7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			**prompts = xrealloc(**prompts, 1, len);
7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcpy(**prompts + plen, msg, len - plen);
7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			plen += mlen;
7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcat(**prompts + plen, "\n", len - plen);
7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			plen++;
7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(msg);
7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_ACCT_EXPIRED:
7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sshpam_account_status = 0;
7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* FALLTHROUGH */
7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_AUTH_ERR:
7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug3("PAM: %s", pam_strerror(sshpam_handle, type));
7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (**prompts != NULL && strlen(**prompts) != 0) {
7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*info = **prompts;
7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				**prompts = NULL;
7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*num = 0;
7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				**echo_on = 0;
7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ctxt->pam_done = -1;
7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(msg);
7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return 0;
7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* FALLTHROUGH */
7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_SUCCESS:
7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (**prompts != NULL) {
7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* drain any accumulated messages */
7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("PAM: %s", **prompts);
7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(&loginmsg, **prompts,
7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    strlen(**prompts));
7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(**prompts);
7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				**prompts = NULL;
7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (type == PAM_SUCCESS) {
7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (!sshpam_authctxt->valid ||
7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    (sshpam_authctxt->pw->pw_uid == 0 &&
7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    options.permit_root_login != PERMIT_YES))
7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					fatal("Internal error: PAM auth "
7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "succeeded when it should have "
7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "failed");
7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				import_environments(&buffer);
7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*num = 0;
7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				**echo_on = 0;
7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ctxt->pam_done = 1;
7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(msg);
7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return (0);
7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("PAM: %s for %s%.100s from %.100s", msg,
7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    sshpam_authctxt->valid ? "" : "illegal user ",
7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    sshpam_authctxt->user,
7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    get_remote_name_or_ip(utmp_len, options.use_dns));
8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* FALLTHROUGH */
8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*num = 0;
8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			**echo_on = 0;
8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(msg);
8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ctxt->pam_done = -1;
8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (-1);
8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (-1);
8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* XXX - see also comment in auth-chall.c:verify_response */
8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_respond(void *ctx, u_int num, char **resp)
8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer buffer;
8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_ctxt *ctxt = ctx;
8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("PAM: %s entering, %u responses", __func__, num);
8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (ctxt->pam_done) {
8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 1:
8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_authenticated = 1;
8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (0);
8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 0:
8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (num != 1) {
8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("PAM: expected one response, got %u", num);
8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&buffer);
8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_authctxt->valid &&
8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (sshpam_authctxt->pw->pw_uid != 0 ||
8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    options.permit_root_login == PERMIT_YES))
8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&buffer, *resp);
8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&buffer, badpw);
8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_free(&buffer);
8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&buffer);
8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (1);
8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_free_ctx(void *ctxtp)
8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_ctxt *ctxt = ctxtp;
8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s entering", __func__);
8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_thread_cleanup();
8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(ctxt);
8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * We don't call sshpam_cleanup() here because we may need the PAM
8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * handle at a later stage, e.g. when setting up a session.  It's
8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * still on the cleanup list, so pam_end() *will* be called before
8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the server process terminates.
8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKbdintDevice sshpam_device = {
8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	"pam",
8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_init_ctx,
8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_query,
8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_respond,
8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_free_ctx
8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKbdintDevice mm_sshpam_device = {
8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	"pam",
8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	mm_sshpam_init_ctx,
8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	mm_sshpam_query,
8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	mm_sshpam_respond,
8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	mm_sshpam_free_ctx
8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This replaces auth-pam.c
8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstart_pam(Authctxt *authctxt)
8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.use_pam)
8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: initialisation requested when UsePAM=no");
8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_init(authctxt) == -1)
8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: initialisation failed");
8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfinish_pam(void)
8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_cleanup();
8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int
9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_pam_account(void)
9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("%s: called", __func__);
9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_account_status != -1)
9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (sshpam_account_status);
9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pam_strerror(sshpam_handle, sshpam_err));
9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_account_status = 0;
9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (sshpam_account_status);
9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err == PAM_NEW_AUTHTOK_REQD)
9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_password_change_required(1);
9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_account_status = 1;
9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (sshpam_account_status);
9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_pam_set_tty(const char *tty)
9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (tty != NULL) {
9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("PAM: setting PAM_TTY to \"%s\"", tty);
9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, tty);
9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (sshpam_err != PAM_SUCCESS)
9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("PAM: failed to set PAM_TTY: %s",
9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    pam_strerror(sshpam_handle, sshpam_err));
9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_pam_setcred(int init)
9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (const void *)&store_conv);
9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS)
9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: failed to set PAM_CONV: %s",
9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (init) {
9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("PAM: establishing credentials");
9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED);
9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("PAM: reinitializing credentials");
9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_err = pam_setcred(sshpam_handle, PAM_REINITIALIZE_CRED);
9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err == PAM_SUCCESS) {
9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_cred_established = 1;
9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_authenticated)
9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: pam_setcred(): %s",
9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("PAM: pam_setcred(): %s",
9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    struct pam_response **resp, void *data)
9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char input[PAM_MAX_MSG_SIZE];
9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_response *reply;
9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s called with %d messages", __func__, n);
9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*resp = NULL;
9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO))
9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((reply = calloc(n, sizeof(*reply))) == NULL)
9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < n; ++i) {
9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_PROMPT_ECHO_OFF:
9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp =
9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    read_passphrase(PAM_MSG_MEMBER(msg, i, msg),
9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    RP_ALLOW_STDIN);
9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp_retcode = PAM_SUCCESS;
9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_PROMPT_ECHO_ON:
9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg));
9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (fgets(input, sizeof input, stdin) == NULL)
9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				input[0] = '\0';
9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((reply[i].resp = strdup(input)) == NULL)
9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp_retcode = PAM_SUCCESS;
9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_ERROR_MSG:
9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_TEXT_INFO:
9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg));
9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp_retcode = PAM_SUCCESS;
9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto fail;
10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*resp = reply;
10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_SUCCESS);
10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fail:
10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; i < n; i++) {
10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (reply[i].resp != NULL)
10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(reply[i].resp);
10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(reply);
10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_CONV_ERR);
10141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct pam_conv tty_conv = { sshpam_tty_conv, NULL };
10171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
10191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * XXX this should be done in the authentication phase, but ssh1 doesn't
10201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * support that
10211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
10221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
10231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_pam_chauthtok(void)
10241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (use_privsep)
10261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Password expired (unable to change with privsep)");
10271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
10281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (const void *)&tty_conv);
10291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS)
10301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: failed to set PAM_CONV: %s",
10311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
10321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("PAM: changing password");
10331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_chauthtok(sshpam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
10341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS)
10351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: pam_chauthtok(): %s",
10361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
10371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
10401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_pam_session(void)
10411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: opening session");
10431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
10441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (const void *)&store_conv);
10451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS)
10461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: failed to set PAM_CONV: %s",
10471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
10481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_open_session(sshpam_handle, 0);
10491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err == PAM_SUCCESS)
10501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_session_open = 1;
10511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else {
10521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_session_open = 0;
10531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		disable_forwarding();
10541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("PAM: pam_open_session(): %s",
10551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
10561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
10611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodis_pam_session_open(void)
10621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return sshpam_session_open;
10641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
10671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Set a PAM environment string. We need to do this so that the session
10681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modules can handle things like Kerberos/GSI credentials that appear
10691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * during the ssh authentication process.
10701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
10711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
10721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_pam_putenv(char *name, char *value)
10731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = 1;
10751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PAM_PUTENV
10761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *compound;
10771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t len;
10781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	len = strlen(name) + strlen(value) + 2;
10801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	compound = xmalloc(len);
10811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(compound, len, "%s=%s", name, value);
10831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = pam_putenv(sshpam_handle, compound);
10841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(compound);
10851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
10861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (ret);
10881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar **
10911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfetch_pam_child_environment(void)
10921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return sshpam_env;
10941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar **
10971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfetch_pam_environment(void)
10981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (pam_getenvlist(sshpam_handle));
11001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
11031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfree_pam_environment(char **env)
11041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char **envp;
11061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (env == NULL)
11081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
11091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (envp = env; *envp; envp++)
11111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(*envp);
11121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(env);
11131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
11161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * "Blind" conversation function for password authentication.  Assumes that
11171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * echo-off prompts are for the password and stores messages for later
11181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * display.
11191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
11201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
11211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
11221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    struct pam_response **resp, void *data)
11231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct pam_response *reply;
11251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
11261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t len;
11271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("PAM: %s called with %d messages", __func__, n);
11291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*resp = NULL;
11311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n <= 0 || n > PAM_MAX_NUM_MSG)
11331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
11341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((reply = calloc(n, sizeof(*reply))) == NULL)
11361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (PAM_CONV_ERR);
11371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < n; ++i) {
11391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
11401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_PROMPT_ECHO_OFF:
11411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (sshpam_password == NULL)
11421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
11431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((reply[i].resp = strdup(sshpam_password)) == NULL)
11441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
11451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp_retcode = PAM_SUCCESS;
11461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
11471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_ERROR_MSG:
11481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case PAM_TEXT_INFO:
11491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			len = strlen(PAM_MSG_MEMBER(msg, i, msg));
11501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (len > 0) {
11511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(&loginmsg,
11521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    PAM_MSG_MEMBER(msg, i, msg), len);
11531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(&loginmsg, "\n", 1);
11541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
11551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((reply[i].resp = strdup("")) == NULL)
11561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto fail;
11571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reply[i].resp_retcode = PAM_SUCCESS;
11581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
11591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
11601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto fail;
11611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
11621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*resp = reply;
11641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_SUCCESS);
11651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fail:
11671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; i < n; i++) {
11681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (reply[i].resp != NULL)
11691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(reply[i].resp);
11701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(reply);
11721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (PAM_CONV_ERR);
11731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct pam_conv passwd_conv = { sshpam_passwd_conv, NULL };
11761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
11781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Attempt password authentication via PAM
11791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
11801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
11811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsshpam_auth_passwd(Authctxt *authctxt, const char *password)
11821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int flags = (options.permit_empty_passwd == 0 ?
11841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    PAM_DISALLOW_NULL_AUTHTOK : 0);
11851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.use_pam || sshpam_handle == NULL)
11871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: %s called when PAM disabled or failed to "
11881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "initialise.", __func__);
11891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_password = password;
11911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_authctxt = authctxt;
11921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
11941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If the user logging in is invalid, or is root but is not permitted
11951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * by PermitRootLogin, use an invalid password to prevent leaking
11961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * information via timing (eg if the PAM config has a delay on fail).
11971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
11981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
11991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    options.permit_root_login != PERMIT_YES))
12001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_password = badpw;
12011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
12031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (const void *)&passwd_conv);
12041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err != PAM_SUCCESS)
12051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("PAM: %s: failed to set PAM_CONV: %s", __func__,
12061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
12071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_err = pam_authenticate(sshpam_handle, flags);
12091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sshpam_password = NULL;
12101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
12111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("PAM: password authentication accepted for %.100s",
12121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    authctxt->user);
12131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
12141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
12151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("PAM: password authentication failed for %.100s: %s",
12161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    authctxt->valid ? authctxt->user : "an illegal user",
12171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pam_strerror(sshpam_handle, sshpam_err));
12181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
12191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
12211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_PAM */
1222