- (djm) Sync with V_3_7 branch:
   - (djm) Fix SSH1 challenge kludge
   - (djm) Bug #671: Fix builds on OpenBSD
   - (djm) Bug #676: Fix PAM stack corruption
   - (djm) Fix bad free() in PAM code
   - (djm) Don't call pam_end before pam_init
   - (djm) Enable build with old OpenSSL again
   - (djm) Trim deprecated options from INSTALL. Mention UsePAM
   - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
diff --git a/ChangeLog b/ChangeLog
index 344aa56..6fd95f7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -74,6 +74,15 @@
  - (bal) "extration" -> "extraction" in ssh-rand-helper.c; repoted by john
 	on #unixhelp@efnet
  - (tim) [configure.ac] add --disable-etc-default-login option. ok djm
+ - (djm) Sync with V_3_7 branch:
+   - (djm) Fix SSH1 challenge kludge
+   - (djm) Bug #671: Fix builds on OpenBSD
+   - (djm) Bug #676: Fix PAM stack corruption
+   - (djm) Fix bad free() in PAM code
+   - (djm) Don't call pam_end before pam_init
+   - (djm) Enable build with old OpenSSL again
+   - (djm) Trim deprecated options from INSTALL. Mention UsePAM
+   - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
 
 20030919
  - (djm) Bug #683: Remove reference to --with-ipv4-default from INSTALL;
@@ -1210,4 +1219,4 @@
  - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo.
    Report from murple@murple.net, diagnosis from dtucker@zip.com.au
 
-$Id: ChangeLog,v 1.3038 2003/09/23 02:50:14 tim Exp $
+$Id: ChangeLog,v 1.3039 2003/09/23 12:12:38 djm Exp $
diff --git a/INSTALL b/INSTALL
index d4b1bdb..86447f3 100644
--- a/INSTALL
+++ b/INSTALL
@@ -101,11 +101,8 @@
 
 There are a few other options to the configure script:
 
---with-pam enables PAM support.
-
---enable-gnome-askpass will build the GNOME passphrase dialog. You
-need a working installation of GNOME, including the development
-headers, for this to work.
+--with-pam enables PAM support. If PAM support is compiled in, it must
+also be enabled in sshd_config (refer to the UsePAM directive).
 
 --with-prngd-socket=/some/file allows you to enable EGD or PRNGD 
 support and to specify a PRNGd socket. Use this if your Unix lacks 
@@ -126,16 +123,6 @@
 --with-osfsia, --without-osfsia will enable or disable OSF1's Security 
 Integration Architecture.  The default for OSF1 machines is enable.
 
---with-kerberos4=PATH will enable Kerberos IV support. You will need
-to have the Kerberos libraries and header files installed for this
-to work. Use the optional PATH argument to specify the root of your
-Kerberos installation.
-
---with-afs=PATH will enable AFS support. You will need to have the
-Kerberos IV and the AFS libraries and header files installed for this
-to work.  Use the optional PATH argument to specify the root of your
-AFS installation. AFS requires Kerberos support to be enabled.
-
 --with-skey=PATH will enable S/Key one time password support. You will 
 need the S/Key libraries and header files installed for this to work.
 
@@ -211,4 +198,4 @@
 http://www.openssh.com/
 
 
-$Id: INSTALL,v 1.59 2003/09/22 03:28:36 dtucker Exp $
+$Id: INSTALL,v 1.60 2003/09/23 12:12:38 djm Exp $
diff --git a/auth-chall.c b/auth-chall.c
index 6b7c8bd..00d6e0e 100644
--- a/auth-chall.c
+++ b/auth-chall.c
@@ -92,7 +92,7 @@
 			xfree(info);
 		}
 		/* if we received more prompts, we're screwed */
-		res = (numprompts != 0);
+		res = (res == 0 && numprompts == 0) ? 0 : -1;
 	}
 	device->free_ctx(authctxt->kbdintctxt);
 	authctxt->kbdintctxt = NULL;
diff --git a/auth-pam.c b/auth-pam.c
index 22706c5..75e2d16 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -31,7 +31,7 @@
 
 /* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */
 #include "includes.h"
-RCSID("$Id: auth-pam.c,v 1.73 2003/09/16 21:24:25 djm Exp $");
+RCSID("$Id: auth-pam.c,v 1.74 2003/09/23 12:12:38 djm Exp $");
 
 #ifdef USE_PAM
 #include <security/pam_appl.h>
@@ -111,12 +111,12 @@
 #endif
 
 
-static pam_handle_t *sshpam_handle;
-static int sshpam_err;
-static int sshpam_authenticated;
-static int sshpam_new_authtok_reqd;
-static int sshpam_session_open;
-static int sshpam_cred_established;
+static pam_handle_t *sshpam_handle = NULL;
+static int sshpam_err = 0;
+static int sshpam_authenticated = 0;
+static int sshpam_new_authtok_reqd = 0;
+static int sshpam_session_open = 0;
+static int sshpam_cred_established = 0;
 
 struct pam_ctxt {
 	sp_pthread_t	 pam_thread;
@@ -136,42 +136,51 @@
 {
 	Buffer buffer;
 	struct pam_ctxt *ctxt;
+	struct pam_response *reply;
 	int i;
 
+	*resp = NULL;
+
 	ctxt = data;
 	if (n <= 0 || n > PAM_MAX_NUM_MSG)
 		return (PAM_CONV_ERR);
-	*resp = xmalloc(n * sizeof **resp);
+
+	if ((reply = malloc(n * sizeof(*reply))) == NULL)
+		return (PAM_CONV_ERR);
+	memset(reply, 0, n * sizeof(*reply));
+
 	buffer_init(&buffer);
 	for (i = 0; i < n; ++i) {
-		resp[i]->resp_retcode = 0;
-		resp[i]->resp = NULL;
 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
 		case PAM_PROMPT_ECHO_OFF:
-			buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg));
+			buffer_put_cstring(&buffer, 
+			    PAM_MSG_MEMBER(msg, i, msg));
 			ssh_msg_send(ctxt->pam_csock, 
 			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer);
 			ssh_msg_recv(ctxt->pam_csock, &buffer);
 			if (buffer_get_char(&buffer) != PAM_AUTHTOK)
 				goto fail;
-			resp[i]->resp = buffer_get_string(&buffer, NULL);
+			reply[i].resp = buffer_get_string(&buffer, NULL);
 			break;
 		case PAM_PROMPT_ECHO_ON:
-			buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg));
+			buffer_put_cstring(&buffer, 
+			    PAM_MSG_MEMBER(msg, i, msg));
 			ssh_msg_send(ctxt->pam_csock, 
 			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer);
 			ssh_msg_recv(ctxt->pam_csock, &buffer);
 			if (buffer_get_char(&buffer) != PAM_AUTHTOK)
 				goto fail;
-			resp[i]->resp = buffer_get_string(&buffer, NULL);
+			reply[i].resp = buffer_get_string(&buffer, NULL);
 			break;
 		case PAM_ERROR_MSG:
-			buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg));
+			buffer_put_cstring(&buffer, 
+			    PAM_MSG_MEMBER(msg, i, msg));
 			ssh_msg_send(ctxt->pam_csock, 
 			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer);
 			break;
 		case PAM_TEXT_INFO:
-			buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg));
+			buffer_put_cstring(&buffer, 
+			    PAM_MSG_MEMBER(msg, i, msg));
 			ssh_msg_send(ctxt->pam_csock, 
 			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer);
 			break;
@@ -181,12 +190,15 @@
 		buffer_clear(&buffer);
 	}
 	buffer_free(&buffer);
+	*resp = reply;
 	return (PAM_SUCCESS);
+
  fail:
-	while (i)
-		xfree(resp[--i]);
-	xfree(*resp);
-	*resp = NULL;
+	for(i = 0; i < n; i++) {
+		if (reply[i].resp != NULL)
+			xfree(reply[i].resp);
+	}
+	xfree(reply);
 	buffer_free(&buffer);
 	return (PAM_CONV_ERR);
 }
@@ -258,6 +270,8 @@
 {
 	(void)arg;
 	debug("PAM: cleanup");
+	if (sshpam_handle == NULL)
+		return;
 	pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
 	if (sshpam_cred_established) {
 		pam_setcred(sshpam_handle, PAM_DELETE_CRED);
@@ -600,40 +614,50 @@
     struct pam_response **resp, void *data)
 {
 	char input[PAM_MAX_MSG_SIZE];
+	struct pam_response *reply;
 	int i;
 
+	*resp = NULL;
+
 	if (n <= 0 || n > PAM_MAX_NUM_MSG)
 		return (PAM_CONV_ERR);
-	*resp = xmalloc(n * sizeof **resp);
+
+	if ((reply = malloc(n * sizeof(*reply))) == NULL)
+		return (PAM_CONV_ERR);
+	memset(reply, 0, n * sizeof(*reply));
+
 	for (i = 0; i < n; ++i) {
 		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
 		case PAM_PROMPT_ECHO_OFF:
-			resp[i]->resp =
+			reply[i].resp =
 			    read_passphrase(PAM_MSG_MEMBER(msg, i, msg), 
 			    RP_ALLOW_STDIN);
-			resp[i]->resp_retcode = PAM_SUCCESS;
+			reply[i].resp_retcode = PAM_SUCCESS;
 			break;
 		case PAM_PROMPT_ECHO_ON:
 			fputs(PAM_MSG_MEMBER(msg, i, msg), stderr);
 			fgets(input, sizeof input, stdin);
-			resp[i]->resp = xstrdup(input);
-			resp[i]->resp_retcode = PAM_SUCCESS;
+			reply[i].resp = xstrdup(input);
+			reply[i].resp_retcode = PAM_SUCCESS;
 			break;
 		case PAM_ERROR_MSG:
 		case PAM_TEXT_INFO:
 			fputs(PAM_MSG_MEMBER(msg, i, msg), stderr);
-			resp[i]->resp_retcode = PAM_SUCCESS;
+			reply[i].resp_retcode = PAM_SUCCESS;
 			break;
 		default:
 			goto fail;
 		}
 	}
+	*resp = reply;
 	return (PAM_SUCCESS);
+
  fail:
-	while (i)
-		xfree(resp[--i]);
-	xfree(*resp);
-	*resp = NULL;
+	for(i = 0; i < n; i++) {
+		if (reply[i].resp != NULL)
+			xfree(reply[i].resp);
+	}
+	xfree(reply);
 	return (PAM_CONV_ERR);
 }
 
diff --git a/cipher-3des1.c b/cipher-3des1.c
index f9a3523..6f9f5dd 100644
--- a/cipher-3des1.c
+++ b/cipher-3des1.c
@@ -29,6 +29,10 @@
 #include "xmalloc.h"
 #include "log.h"
 
+#if OPENSSL_VERSION_NUMBER < 0x00906000L
+#define SSH_OLD_EVP
+#endif
+
 /*
  * This is used by SSH1:
  *
diff --git a/cipher-aes.c b/cipher-aes.c
index c41def6..7ba9501 100644
--- a/cipher-aes.c
+++ b/cipher-aes.c
@@ -31,6 +31,10 @@
 #include "xmalloc.h"
 #include "log.h"
 
+#if OPENSSL_VERSION_NUMBER < 0x00906000L
+#define SSH_OLD_EVP
+#endif
+
 #define RIJNDAEL_BLOCKSIZE 16
 struct ssh_rijndael_ctx
 {
diff --git a/cipher-bf1.c b/cipher-bf1.c
index 64578ba..5af695c 100644
--- a/cipher-bf1.c
+++ b/cipher-bf1.c
@@ -28,6 +28,11 @@
 #include <openssl/evp.h>
 #include "xmalloc.h"
 #include "log.h"
+
+#if OPENSSL_VERSION_NUMBER < 0x00906000L
+#define SSH_OLD_EVP
+#endif
+
 /*
  * SSH1 uses a variation on Blowfish, all bytes must be swapped before
  * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
diff --git a/cipher-ctr.c b/cipher-ctr.c
index a2bab5c..4f0814b 100644
--- a/cipher-ctr.c
+++ b/cipher-ctr.c
@@ -21,6 +21,10 @@
 #include "log.h"
 #include "xmalloc.h"
 
+#if OPENSSL_VERSION_NUMBER < 0x00906000L
+#define SSH_OLD_EVP
+#endif
+
 #if OPENSSL_VERSION_NUMBER < 0x00907000L
 #include "rijndael.h"
 #define AES_KEY rijndael_ctx
@@ -135,7 +139,9 @@
 	aes_ctr.init = ssh_aes_ctr_init;
 	aes_ctr.cleanup = ssh_aes_ctr_cleanup;
 	aes_ctr.do_cipher = ssh_aes_ctr;
+#ifndef SSH_OLD_EVP
 	aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
 	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
+#endif
 	return (&aes_ctr);
 }
diff --git a/cipher.c b/cipher.c
index e7c3c54..ce53367 100644
--- a/cipher.c
+++ b/cipher.c
@@ -87,9 +87,11 @@
 	{ "rijndael-cbc@lysator.liu.se",
 				SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
 #endif
+#if OPENSSL_VERSION_NUMBER >= 0x00906000L
 	{ "aes128-ctr", 	SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr },
 	{ "aes192-ctr", 	SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr },
 	{ "aes256-ctr", 	SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr },
+#endif
 
 	{ NULL,			SSH_CIPHER_ILLEGAL, 0, 0, NULL }
 };
diff --git a/configure.ac b/configure.ac
index dbb08fb..164326c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-# $Id: configure.ac,v 1.165 2003/09/23 02:50:14 tim Exp $
+# $Id: configure.ac,v 1.166 2003/09/23 12:12:38 djm Exp $
 
 AC_INIT
 AC_CONFIG_SRCDIR([ssh.c])
@@ -480,7 +480,7 @@
 	sys/cdefs.h sys/mman.h sys/pstat.h sys/select.h sys/stat.h \
 	sys/stropts.h sys/sysmacros.h sys/time.h sys/timers.h \
 	sys/un.h time.h tmpdir.h ttyent.h usersec.h \
-	util.h utime.h utmp.h utmpx.h)
+	util.h utime.h utmp.h utmpx.h vis.h)
 
 # Checks for libraries.
 AC_CHECK_FUNC(yp_match, , AC_CHECK_LIB(nsl, yp_match))
diff --git a/log.c b/log.c
index 58ce8e5..9bce255 100644
--- a/log.c
+++ b/log.c
@@ -40,6 +40,9 @@
 #include "xmalloc.h"
 
 #include <syslog.h>
+#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
+# include <vis.h>
+#endif
 
 static LogLevel log_level = SYSLOG_LEVEL_INFO;
 static int log_on_stderr = 1;
diff --git a/servconf.c b/servconf.c
index 71e28b3..58f49a2 100644
--- a/servconf.c
+++ b/servconf.c
@@ -110,7 +110,7 @@
 {
 	/* Portable-specific options */
 	if (options->use_pam == -1)
-		options->use_pam = 1;
+		options->use_pam = 0;
 
 	/* Standard Options */
 	if (options->protocol == SSH_PROTO_UNKNOWN)
diff --git a/sftp-int.c b/sftp-int.c
index 94299aa..c93eaab 100644
--- a/sftp-int.c
+++ b/sftp-int.c
@@ -351,6 +351,7 @@
 		for (i = j = 0; i <= strlen(cp); i++) {
 			if (cp[i] == quot) {	/* Found quote */
 				(*path)[j] = '\0';
+				i++;
 				break;
 			}
 			if (cp[i] == '\0') {	/* End of string */