--- old/usr/src/cmd/ssh/sshd/auth2-pam.c	2016-08-16 20:42:25.247080296 -0400
+++ /dev/null	2016-08-16 20:42:25.000000000 -0400
@@ -1,458 +0,0 @@
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-
-RCSID("$Id: auth2-pam.c,v 1.14 2002/06/28 16:48:12 mouring Exp $");
-
-#ifdef USE_PAM
-#include <security/pam_appl.h>
-
-#include "ssh.h"
-#include "ssh2.h"
-#include "auth.h"
-#include "auth-pam.h"
-#include "auth-options.h"
-#include "packet.h"
-#include "xmalloc.h"
-#include "dispatch.h"
-#include "canohost.h"
-#include "log.h"
-#include "servconf.h"
-#include "misc.h"
-
-#ifdef HAVE_BSM
-#include "bsmaudit.h"
-#endif /* HAVE_BSM */
-
-extern u_int utmp_len;
-extern ServerOptions options;
-
-extern Authmethod method_kbdint;
-extern Authmethod method_passwd;
-
-#define SSHD_PAM_KBDINT_SVC "sshd-kbdint"
-/* Maximum attempts for changing expired password */
-#define DEF_ATTEMPTS 3
-
-static int do_pam_conv_kbd_int(int num_msg, 
-    struct pam_message **msg, struct pam_response **resp, 
-    void *appdata_ptr);
-static void input_userauth_info_response_pam(int type,
-					     u_int32_t seqnr,
-					     void *ctxt);
-
-static struct pam_conv conv2 = {
-	do_pam_conv_kbd_int,
-	NULL,
-};
-
-static void do_pam_kbdint_cleanup(pam_handle_t *pamh);
-static void do_pam_kbdint(Authctxt *authctxt);
-
-void
-auth2_pam(Authctxt *authctxt)
-{
-	if (authctxt->user == NULL)
-		fatal("auth2_pam: internal error: no user");
-	if (authctxt->method == NULL)
-		fatal("auth2_pam: internal error: no method");
-
-	conv2.appdata_ptr = authctxt;
-	new_start_pam(authctxt, &conv2);
-
-	authctxt->method->method_data = NULL; /* freed in the conv func */
-	dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE,
-	    &input_userauth_info_response_pam);
-
-	/*
-	 * Since password userauth and keyboard-interactive userauth
-	 * both use PAM, and since keyboard-interactive is so much
-	 * better than password userauth, we should not allow the user
-	 * to try password userauth after trying keyboard-interactive.
-	 */
-	if (method_passwd.enabled)
-		*method_passwd.enabled = 0;
-
-	do_pam_kbdint(authctxt);
-
-	dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
-}
-
-static void
-do_pam_kbdint(Authctxt *authctxt)
-{
-	int		 retval, retval2;
-	pam_handle_t	*pamh = authctxt->pam->h;
-	const char	*where = "authenticating";
-	char		*text = NULL;
-
-	debug2("Calling pam_authenticate()");
-	retval = pam_authenticate(pamh,
-	    options.permit_empty_passwd ? 0 :
-	    PAM_DISALLOW_NULL_AUTHTOK);
-
-	if (retval != PAM_SUCCESS)
-		goto cleanup;
-
-	debug2("kbd-int: pam_authenticate() succeeded");
-	where = "authorizing";
-	retval = pam_acct_mgmt(pamh, 0);
-
-	if (retval == PAM_NEW_AUTHTOK_REQD) {
-		if (authctxt->valid && authctxt->pw != NULL) {
-			/* send password expiration warning */
-			message_cat(&text,
-			    gettext("Warning: Your password has expired,"
-			    " please change it now."));
-			packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
-			packet_put_cstring("");		/* name */
-			packet_put_utf8_cstring(text);	/* instructions */
-			packet_put_cstring("");		/* language, unused */
-			packet_put_int(0);
-			packet_send();
-			packet_write_wait();
-			debug("expiration message sent");
-			if (text)
-				xfree(text);
-			/*
-			 * wait for the response so it does not mix
-			 * with the upcoming PAM conversation
-			 */
-			packet_read_expect(SSH2_MSG_USERAUTH_INFO_RESPONSE);
-			/*
-			 * Can't use temporarily_use_uid() and restore_uid()
-			 * here because we need (euid == 0 && ruid == pw_uid)
-			 * whereas temporarily_use_uid() arranges for
-			 * (suid = 0 && euid == pw_uid && ruid == pw_uid).
-			 */
-			(void) setreuid(authctxt->pw->pw_uid, -1);
-			debug2("kbd-int: changing expired password");
-			where = "changing authentication tokens (password)";
-			/*
-			 * Depending on error returned from pam_chauthtok, we
-			 * need to try to change password a few times before
-			 * we error out and return.
-			 */
-			int tries = 0;
-			while ((retval = pam_chauthtok(pamh,
-			    PAM_CHANGE_EXPIRED_AUTHTOK)) != PAM_SUCCESS) {
-				if (tries++ < DEF_ATTEMPTS) {
-					if ((retval == PAM_AUTHTOK_ERR) ||
-					    (retval == PAM_TRY_AGAIN)) {
-						continue;
-					}
-				}
-				break;
-			}
-			audit_sshd_chauthtok(retval, authctxt->pw->pw_uid,
-				authctxt->pw->pw_gid);
-			(void) setreuid(0, -1);
-		} else {
-			retval = PAM_PERM_DENIED;
-		}
-	}
-
-	if (retval != PAM_SUCCESS)
-		goto cleanup;
-
-	authctxt->pam->state |= PAM_S_DONE_ACCT_MGMT;
-
-	retval = finish_userauth_do_pam(authctxt);
-
-	if (retval != PAM_SUCCESS)
-		goto cleanup;
-
-	/*
-	 * PAM handle stays around so we can call pam_close_session()
-	 * on it later.
-	 */
-	authctxt->method->authenticated = 1;
-	debug2("kbd-int: success (pam->state == %x)", authctxt->pam->state);
-	return;
-
-cleanup:
-	/*
-	 * Check for abandonment and cleanup.  When kbdint is abandoned
-	 * authctxt->pam->h is NULLed and by this point a new handle may
-	 * be allocated.
-	 */
-	if (authctxt->pam->h != pamh) {
-		log("Keyboard-interactive (PAM) userauth abandoned "
-		    "while %s", where);
-		if ((retval2 = pam_end(pamh, retval)) != PAM_SUCCESS) {
-			log("Cannot close PAM handle after "
-			    "kbd-int userauth abandonment[%d]: %.200s",
-			    retval2, PAM_STRERROR(pamh, retval2));
-		}
-		authctxt->method->abandoned = 1;
-
-		/*
-		 * Avoid double counting; these are incremented in
-		 * kbdint_pam_abandon() so that they reflect the correct
-		 * count when userauth_finish() is called before
-		 * unwinding the dispatch_run() loop, but they are
-		 * incremented again in input_userauth_request() when
-		 * the loop is unwound, right here.
-		 */
-		if (authctxt->method->abandons)
-			authctxt->method->abandons--;
-		if (authctxt->method->attempts)
-			authctxt->method->attempts--;
-	}
-	else {
-		/* Save error value for pam_end() */
-		authctxt->pam->last_pam_retval = retval;
-		log("Keyboard-interactive (PAM) userauth failed[%d] "
-		    "while %s: %.200s", retval, where,
-		    PAM_STRERROR(pamh, retval));
-		/* pam handle can be reused elsewhere, so no pam_end() here */
-	}
-
-	return;
-}
-
-static int
-do_pam_conv_kbd_int(int num_msg, struct pam_message **msg,
-    struct pam_response **resp, void *appdata_ptr)
-{
-	int i, j;
-	char *text;
-	Convctxt *conv_ctxt;
-	Authctxt *authctxt = (Authctxt *)appdata_ptr;
-
-	if (!authctxt || !authctxt->method) {
-		debug("Missing state during PAM conversation");
-		return PAM_CONV_ERR;
-	}
-
-	conv_ctxt = xmalloc(sizeof(Convctxt));
-	(void) memset(conv_ctxt, 0, sizeof(Convctxt));
-	conv_ctxt->finished = 0;
-	conv_ctxt->num_received = 0;
-	conv_ctxt->num_expected = 0;
-	conv_ctxt->prompts = xmalloc(sizeof(int) * num_msg);
-	conv_ctxt->responses = xmalloc(sizeof(struct pam_response) * num_msg);
-	(void) memset(conv_ctxt->responses, 0, sizeof(struct pam_response) * num_msg);
-
-	text = NULL;
-	for (i = 0, conv_ctxt->num_expected = 0; i < num_msg; i++) {
-		int style = PAM_MSG_MEMBER(msg, i, msg_style);
-		switch (style) {
-		case PAM_PROMPT_ECHO_ON:
-			debug2("PAM echo on prompt: %s",
-				PAM_MSG_MEMBER(msg, i, msg));
-			conv_ctxt->num_expected++;
-			break;
-		case PAM_PROMPT_ECHO_OFF:
-			debug2("PAM echo off prompt: %s",
-				PAM_MSG_MEMBER(msg, i, msg));
-			conv_ctxt->num_expected++;
-			break;
-		case PAM_TEXT_INFO:
-			debug2("PAM text info prompt: %s",
-				PAM_MSG_MEMBER(msg, i, msg));
-			message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
-			break;
-		case PAM_ERROR_MSG:
-			debug2("PAM error prompt: %s",
-				PAM_MSG_MEMBER(msg, i, msg));
-			message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
-			break;
-		default:
-			/* Capture all these messages to be sent at once */
-			message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
-			break;
-		}
-	}
-
-	if (conv_ctxt->num_expected == 0 && text == NULL) {
-		xfree(conv_ctxt->prompts);
-		xfree(conv_ctxt->responses);
-		xfree(conv_ctxt);
-		return PAM_SUCCESS;
-	}
-
-	authctxt->method->method_data = (void *) conv_ctxt;
-
-	packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
-	packet_put_cstring("");	/* Name */
-	packet_put_utf8_cstring(text ? text : "");	/* Instructions */
-	packet_put_cstring("");	/* Language */
-	packet_put_int(conv_ctxt->num_expected);
-
-	if (text)
-		xfree(text);
-	
-	for (i = 0, j = 0; i < num_msg; i++) {
-		int style = PAM_MSG_MEMBER(msg, i, msg_style);
-		
-		/* Skip messages which don't need a reply */
-		if (style != PAM_PROMPT_ECHO_ON && style != PAM_PROMPT_ECHO_OFF)
-			continue;
-		
-		conv_ctxt->prompts[j++] = i;
-		packet_put_utf8_cstring(PAM_MSG_MEMBER(msg, i, msg));
-		packet_put_char(style == PAM_PROMPT_ECHO_ON);
-	}
-	packet_send();
-	packet_write_wait();
-
-	/*
-	 * Here the dispatch_run() loop is nested.  It should be unwound
-	 * if keyboard-interactive userauth is abandoned (or restarted;
-	 * same thing).
-	 *
-	 * The condition for breaking out of the nested dispatch_run() loop is
-	 *     ((got kbd-int info reponse) || (kbd-int abandoned))
-	 *
-	 * conv_ctxt->finished is set in either of those cases.
-	 *
-	 * When abandonment is detected the conv_ctxt->finished is set as
-	 * is conv_ctxt->abandoned, causing this function to signal
-	 * userauth nested dispatch_run() loop unwinding and to return
-	 * PAM_CONV_ERR;
-	 */
-	debug2("Nesting dispatch_run loop");
-	dispatch_run(DISPATCH_BLOCK, &conv_ctxt->finished, appdata_ptr);
-	debug2("Nested dispatch_run loop exited");
-
-	if (conv_ctxt->abandoned) {
-		authctxt->unwind_dispatch_loop = 1;
-		xfree(conv_ctxt->prompts);
-		xfree(conv_ctxt->responses);
-		xfree(conv_ctxt);
-		debug("PAM conv function returns PAM_CONV_ERR");
-		return PAM_CONV_ERR;
-	}
-
-	if (conv_ctxt->num_received == conv_ctxt->num_expected) {
-		*resp = conv_ctxt->responses;
-		xfree(conv_ctxt->prompts);
-		xfree(conv_ctxt);
-		debug("PAM conv function returns PAM_SUCCESS");
-		return PAM_SUCCESS;
-	}
-
-	debug("PAM conv function returns PAM_CONV_ERR");
-	xfree(conv_ctxt->prompts);
-	xfree(conv_ctxt->responses);
-	xfree(conv_ctxt);
-	return PAM_CONV_ERR;
-}
-
-static void
-input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt)
-{
-	Authctxt *authctxt = ctxt;
-	Convctxt *conv_ctxt;
-	unsigned int nresp = 0, rlen = 0, i = 0;
-	char *resp;
-
-	if (authctxt == NULL)
-		fatal("input_userauth_info_response_pam: no authentication context");
-
-	/* Check for spurious/unexpected info response */
-	if (method_kbdint.method_data == NULL) {
-		debug("input_userauth_info_response_pam: no method context");
-		return;
-	}
-
-	conv_ctxt = (Convctxt *) method_kbdint.method_data;
-
-	nresp = packet_get_int();	/* Number of responses. */
-	debug("got %d responses", nresp);
-
-
-#if 0
-	if (nresp != conv_ctxt->num_expected)
-		fatal("%s: Received incorrect number of responses "
-		    "(expected %d, received %u)", __func__, 
-		    conv_ctxt->num_expected, nresp);
-#endif
-
-	if (nresp > 100)
-		fatal("%s: too many replies", __func__);
-
-	for (i = 0; i < nresp && i < conv_ctxt->num_expected ; i++) {
-		int j = conv_ctxt->prompts[i];
-
-		/*
-		 * We assume that ASCII charset is used for password
-		 * although the protocol requires UTF-8 encoding for the
-		 * password string. Therefore, we don't perform code
-		 * conversion for the string.
-		 */
-		resp = packet_get_string(&rlen);
-		if (i < conv_ctxt->num_expected) {
-			conv_ctxt->responses[j].resp_retcode = PAM_SUCCESS;
-			conv_ctxt->responses[j].resp = xstrdup(resp);
-			conv_ctxt->num_received++;
-		}
-		xfree(resp);
-	}
-
-	if (nresp < conv_ctxt->num_expected)
-		fatal("%s: too few replies (%d < %d)", __func__,
-		    nresp, conv_ctxt->num_expected);
-
-	/* XXX - This could make a covert channel... */
-	if (nresp > conv_ctxt->num_expected)
-		debug("Ignoring additional PAM replies");
-
-	conv_ctxt->finished = 1;
-
-	packet_check_eom();
-}
-
-#if 0
-int
-kbdint_pam_abandon_chk(Authctxt *authctxt, Authmethod *method)
-{
-	if (!method)
-		return 0; /* fatal(), really; it'll happen somewhere else */
-
-	if (!method->method_data)
-		return 0;
-
-	return 1;
-}
-#endif
-
-void
-kbdint_pam_abandon(Authctxt *authctxt, Authmethod *method)
-{
-	Convctxt *conv_ctxt;
-
-	/*
-	 * But, if it ever becomes desirable and possible to support
-	 * kbd-int userauth abandonment, here's what must be done.
-	 */
-	if (!method)
-		return;
-
-	if (!method->method_data)
-		return;
-
-	conv_ctxt = (Convctxt *) method->method_data;
-
-	/* dispatch_run() loop will exit */
-	conv_ctxt->abandoned = 1;
-	conv_ctxt->finished = 1;
-
-	/*
-	 * The method_data will be free in the corresponding, active
-	 * conversation function
-	 */
-	method->method_data = NULL;
-
-	/* update counts that can't be updated elsewhere */
-	method->abandons++;
-	method->attempts++;
-
-	/* Finally, we cannot re-use the current current PAM handle */
-	authctxt->pam->h = NULL;    /* Let the conv function cleanup */
-}
-#endif
