- Import of patch from Ben Taylor <bent@clark.net>:
   - Improved PAM support
   - "uninstall" rule for Makefile
   - utmpx support
   - Should fix PAM problems on Solaris
diff --git a/ChangeLog b/ChangeLog
index 1b48095..39304e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+19991209
+ - Import of patch from Ben Taylor <bent@clark.net>:
+   - Improved PAM support
+   - "uninstall" rule for Makefile
+   - utmpx support
+   - Should fix PAM problems on Solaris
+
 19991208
  - Compile fix for Solaris with /dev/ptmx from 
    David Agraz <dagraz@jahoopa.com>
diff --git a/Makefile.in b/Makefile.in
index 80b0a6d..232f8e0 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -103,6 +103,36 @@
 		$(INSTALL) -m644 sshd_config $(sysconfdir)/sshd_config; \
 	fi
 
+uninstallall:	uninstall
+	-rm -f $(sysconfdir)/ssh_config
+	-rm -f $(sysconfdir)/sshd_config
+	-rmdir $(sysconfdir)
+	-rmdir $(bindir)
+	-rmdir $(sbindir)
+	-rmdir $(mandir)/man1
+	-rmdir $(mandir)/man8
+	-rmdir $(mandir)
+	-rmdir $(libexecdir)
+
+uninstall: 
+	-rm -f $(bindir)/ssh
+	-rm -f $(bindir)/scp
+	-rm -f $(bindir)/ssh-add
+	-rm -f $(bindir)/ssh-agent
+	-rm -f $(bindir)/ssh-keygen
+	-rm -f $(sbindir)/sshd
+	-rm -f $(mandir)/man1/ssh.1
+	-rm -f $(mandir)/man1/scp.1
+	-rm -f $(mandir)/man1/ssh-add.1
+	-rm -f $(mandir)/man1/ssh-agent.1
+	-rm -f $(mandir)/man1/ssh-keygen.1
+	-rm -f $(mandir)/man8/sshd.8
+	-rm -f $(bindir)/slogin
+	-rm -f $(mandir)/man1/slogin.1
+	-rm -f $(mandir)/man1/slogin.1
+	-rm -f ${ASKPASS_PROGRAM}
+	-rmdir $(libexecdir)/ssh ;
+
 distclean: clean
 	rm -f Makefile config.h core *~
 
diff --git a/acconfig.h b/acconfig.h
index 29ec078..811c00d 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -24,6 +24,9 @@
 /* Define is utmp.h has a ut_host field */
 #undef HAVE_HOST_IN_UTMP
 
+/* Define is utmpx.h has a ut_host field */
+#undef HAVE_HOST_IN_UTMPX
+
 /* Define is libutil has login() function */
 #undef HAVE_LIBUTIL_LOGIN
 
@@ -85,6 +88,10 @@
 # include <utmp.h> /* For _PATH_XXX */
 #endif 
 
+#ifdef HAVE_UTMPX_H
+# include <utmpx.h> /* For _PATH_XXX */
+#endif 
+
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h> /* For timersub */
 #endif
@@ -96,13 +103,13 @@
 #ifndef SHUT_RDWR
 enum
 {
-  SHUT_RD = 0,    /* No more receptions.  */
-#define SHUT_RD   SHUT_RD
-  SHUT_WR,    /* No more transmissions.  */
-#define SHUT_WR   SHUT_WR
-  SHUT_RDWR   /* No more receptions or transmissions.  */
-#define SHUT_RDWR SHUT_RDWR
+  SHUT_RD = 0,		/* No more receptions.  */
+  SHUT_WR,			/* No more transmissions.  */
+  SHUT_RDWR			/* No more receptions or transmissions.  */
 };
+# define SHUT_RD   SHUT_RD
+# define SHUT_WR   SHUT_WR
+# define SHUT_RDWR SHUT_RDWR
 #endif
 
 /* If sys/types.h does not supply intXX_t, supply them ourselves */
@@ -164,25 +171,44 @@
 # define quad_t int64_t
 #endif
 
+/* If _PATH_LASTLOG is not defined by system headers, set it to the */
+/* lastlog file detected by autoconf */
 #ifndef _PATH_LASTLOG
 # ifdef LASTLOG_LOCATION
 #  define _PATH_LASTLOG LASTLOG_LOCATION
 # endif
 #endif
 
+/* Use utmpx if supported */
+#ifdef HAVE_UTMPX_H
+# define UTMP_STR utmpx
+#else 
+# ifdef HAVE_UTMP_H
+#  define UTMP_STR utmp
+# endif
+#endif
+
 #ifndef _PATH_UTMP
-# ifdef UTMP_FILE
-#  define _PATH_UTMP UTMP_FILE
+# ifdef UTMPX_FILE
+#  define _PATH_UTMP UTMPX_FILE
 # else
-#  define _PATH_UTMP "/var/adm/utmp"
+#  ifdef UTMP_FILE
+#   define _PATH_UTMP UTMP_FILE
+#  else
+#   define _PATH_UTMP "/var/adm/utmp"
+#  endif
 # endif
 #endif
 
 #ifndef _PATH_WTMP
-# ifdef WTMP_FILE
-#  define _PATH_WTMP WTMP_FILE
+# ifdef WTMPX_FILE
+#  define _PATH_WTMP WTMPX_FILE
 # else
-#  define _PATH_WTMP "/var/adm/wtmp"
+#  ifdef WTMP_FILE
+#   define _PATH_WTMP WTMP_FILE
+#  else
+#   define _PATH_WTMP "/var/adm/wtmp"
+#  endif
 # endif
 #endif
 
@@ -219,9 +245,9 @@
          (result)->tv_usec += 1000000;                        \
       }                                                       \
    } while (0)
-
 #endif
 
+/* In older versions of libpam, pam_strerror takes a single argument */
 #ifdef HAVE_OLD_PAM
 # define PAM_STRERROR(a,b) pam_strerror((b))
 #else
@@ -231,3 +257,4 @@
 #ifndef __P
 # define __P(x) x
 #endif
+
diff --git a/bsd-login.c b/bsd-login.c
index dcbabe0..9c12065 100644
--- a/bsd-login.c
+++ b/bsd-login.c
@@ -45,47 +45,59 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <utmp.h>
+#ifdef HAVE_UTMPX_H
+# include <utmpx.h>
+#endif
+#ifdef HAVE_UTMP_H
+# include <utmp.h>
+#endif
 #include <stdio.h>
 
 void
 login(utp)
-	struct utmp *utp;
+	struct UTMP_STR *utp;
 {
-	struct utmp old_ut;
+	struct UTMP_STR old_ut;
 	register int fd;
 	int tty;
 
 #ifndef UT_LINESIZE
 # define UT_LINESIZE (sizeof(old_ut.ut_line))
-# define UT_NAMESIZE (sizeof(old_ut.ut_name))
+# ifdef HAVE_UTMPX_H
+#  define UT_NAMESIZE (sizeof(old_ut.ut_user))
+# else
+#  define UT_NAMESIZE (sizeof(old_ut.ut_name))
+# endif
 # ifdef HAVE_HOST_IN_UTMP
 #  define UT_HOSTSIZE (sizeof(old_ut.ut_host))
 # endif
+# ifdef HAVE_HOST_IN_UTMPX
+#  define UT_HOSTSIZE (sizeof(old_ut.ut_host))
+# endif
 #endif
 
 	tty = ttyslot();
 	if (tty > 0 && (fd = open(_PATH_UTMP, O_RDWR|O_CREAT, 0644)) >= 0) {
-#ifdef HAVE_HOST_IN_UTMP
-		(void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
+#ifdef HAVE_HOST_IN_UTMP || HAVE_HOST_IN_UTMPX
+		(void)lseek(fd, (off_t)(tty * sizeof(struct UTMP_STR)), SEEK_SET);
 		/*
 		 * Prevent luser from zero'ing out ut_host.
 		 * If the new ut_line is empty but the old one is not
 		 * and ut_line and ut_name match, preserve the old ut_line.
 		 */
-		if (read(fd, &old_ut, sizeof(struct utmp)) ==
-		    sizeof(struct utmp) && utp->ut_host[0] == '\0' &&
+		if (read(fd, &old_ut, sizeof(struct UTMP_STR)) ==
+		    sizeof(struct UTMP_STR) && utp->ut_host[0] == '\0' &&
 		    old_ut.ut_host[0] != '\0' &&
 		    strncmp(old_ut.ut_line, utp->ut_line, UT_LINESIZE) == 0 &&
 		    strncmp(old_ut.ut_name, utp->ut_name, UT_NAMESIZE) == 0)
 			(void)memcpy(utp->ut_host, old_ut.ut_host, UT_HOSTSIZE);
-#endif /* HAVE_HOST_IN_UTMP */
-		(void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
-		(void)write(fd, utp, sizeof(struct utmp));
+#endif /* HAVE_HOST_IN_UTMP || HAVE_HOST_IN_UTMPX */
+		(void)lseek(fd, (off_t)(tty * sizeof(struct UTMP_STR)), SEEK_SET);
+		(void)write(fd, utp, sizeof(struct UTMP_STR));
 		(void)close(fd);
 	}
 	if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) {
-		(void)write(fd, utp, sizeof(struct utmp));
+		(void)write(fd, utp, sizeof(struct UTMP_STR));
 		(void)close(fd);
 	}
 }
diff --git a/configure.in b/configure.in
index f1027ef..e039552 100644
--- a/configure.in
+++ b/configure.in
@@ -56,7 +56,7 @@
 AC_CHECK_LIB(pam, pam_authenticate, , )
 
 dnl Checks for header files.
-AC_CHECK_HEADERS(endian.h lastlog.h login.h maillock.h netgroup.h paths.h pty.h shadow.h util.h utmp.h sys/select.h sys/stropts.h sys/time.h)
+AC_CHECK_HEADERS(endian.h lastlog.h login.h maillock.h netgroup.h paths.h pty.h shadow.h util.h utmp.h utmpx.h sys/select.h sys/stropts.h sys/time.h)
 
 dnl Checks for library functions.
 AC_CHECK_FUNCS(arc4random mkdtemp openpty _getpty setenv setlogin setproctitle snprintf strlcat strlcpy vsnprintf)
@@ -198,6 +198,13 @@
 	[AC_MSG_RESULT(no)]
 )
 
+dnl Check for ut_host field in utmpx
+AC_MSG_CHECKING([whether utmpx.h has ut_host field])
+AC_EGREP_HEADER(ut_host, utmpx.h, 
+	[AC_DEFINE(HAVE_HOST_IN_UTMPX) AC_MSG_RESULT(yes); ], 
+	[AC_MSG_RESULT(no)]
+)
+
 dnl Look for lastlog location
 AC_MSG_CHECKING([location of lastlog file])
 for lastlog in /var/log/lastlog /var/adm/lastlog /etc/security/lastlog ; do
diff --git a/login.c b/login.c
index 81bae82..ff41845 100644
--- a/login.c
+++ b/login.c
@@ -18,9 +18,14 @@
  */
 
 #include "includes.h"
-RCSID("$Id: login.c,v 1.5 1999/11/25 02:08:31 damien Exp $");
+RCSID("$Id: login.c,v 1.6 1999/12/08 23:16:55 damien Exp $");
 
-#include <utmp.h>
+#ifdef HAVE_UTMPX_H
+# include <utmpx.h>
+#endif
+#ifdef HAVE_UTMP_H
+# include <utmp.h>
+#endif
 #include "ssh.h"
 
 #ifdef HAVE_UTIL_H
@@ -83,15 +88,20 @@
 	int fd;
 	struct lastlog ll;
 	char *lastlog;
-	struct utmp u;
+	struct UTMP_STR u;
 	const char *utmp, *wtmp;
 
 	/* Construct an utmp/wtmp entry. */
 	memset(&u, 0, sizeof(u));
 	strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
+#ifdef HAVE_UTMPX_H
+	u.ut_tv.tv_sec = time(NULL);
+	strncpy(u.ut_user, user, sizeof(u.ut_name));
+#else
 	u.ut_time = time(NULL);
 	strncpy(u.ut_name, user, sizeof(u.ut_name));
-#ifdef HAVE_HOST_IN_UTMP
+#endif
+#if defined(HAVE_HOST_IN_UTMP) || defined(HAVE_HOST_IN_UTMPX)
 	strncpy(u.ut_host, host, sizeof(u.ut_host));
 #endif
 
diff --git a/pty.c b/pty.c
index acd81c9..c6c7363 100644
--- a/pty.c
+++ b/pty.c
@@ -14,11 +14,15 @@
  */
 
 #include "includes.h"
-RCSID("$Id: pty.c,v 1.7 1999/12/07 21:53:52 damien Exp $");
+RCSID("$Id: pty.c,v 1.8 1999/12/08 23:16:55 damien Exp $");
 
 #include "pty.h"
 #include "ssh.h"
 
+#ifdef HAVE_DEV_PTMX
+#include <sys/stropts.h>
+#endif /* HAVE_DEV_PTMX */
+
 /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
 #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
 #undef HAVE_DEV_PTMX
diff --git a/sshd.c b/sshd.c
index 0c15e28..2ff8f45 100644
--- a/sshd.c
+++ b/sshd.c
@@ -11,7 +11,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: sshd.c,v 1.35 1999/12/07 04:38:32 damien Exp $");
+RCSID("$Id: sshd.c,v 1.36 1999/12/08 23:16:55 damien Exp $");
 
 #include "xmalloc.h"
 #include "rsa.h"
@@ -138,7 +138,8 @@
 #ifdef HAVE_LIBPAM
 static int pamconv(int num_msg, const struct pam_message **msg,
 	  struct pam_response **resp, void *appdata_ptr);
-void do_pam_account_and_session(char *username, char *remote_user);
+void do_pam_account(char *username, char *remote_user);
+void do_pam_session(char *username, char *ttyname);
 void pam_cleanup_proc(void *context);
 
 static struct pam_conv conv = {
@@ -228,7 +229,7 @@
 	}
 }
 
-void do_pam_account_and_session(char *username, char *remote_user)
+void do_pam_account(char *username, char *remote_user)
 {
 	int pam_retval;
 
@@ -254,12 +255,22 @@
 		log("PAM rejected by account configuration: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
 		do_fake_authloop(username);
 	}
+}
+
+void do_pam_session(char *username, char *ttyname)
+{
+	int pam_retval;
+
+	if (ttyname != NULL) {
+		debug("PAM setting tty to \"%.200s\"", ttyname);
+		pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname);
+		if (pam_retval != PAM_SUCCESS)
+			fatal("PAM set tty failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+	}
 
 	pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
-	if (pam_retval != PAM_SUCCESS) {
-		log("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
-		do_fake_authloop(username);
-	}
+	if (pam_retval != PAM_SUCCESS)
+		fatal("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
 }
 #endif /* HAVE_LIBPAM */
 
@@ -1476,12 +1487,16 @@
 			pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
 			if (pam_retval == PAM_SUCCESS) {
 				log("PAM Password authentication accepted for user \"%.100s\"", pw->pw_name);
+				memset(password, 0, strlen(password));
+				xfree(password);
 				authenticated = 1;
 				break;
 			}
 
 			log("PAM Password authentication for \"%.100s\" failed: %s", 
 				pw->pw_name, PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+			memset(password, 0, strlen(password));
+			xfree(password);
 			break;
 #else /* HAVE_LIBPAM */
 			/* Try authentication with the password. */
@@ -1561,30 +1576,18 @@
 			packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
 #else /* HAVE_LIBPAM */
 		if (authenticated) {
-			do_pam_account_and_session(pw->pw_name, client_user);
+			do_pam_account(pw->pw_name, client_user);
 
-			/* Clean up */
 			if (client_user != NULL)
 				xfree(client_user);
 
-			if (password != NULL) {
-				memset(password, 0, strlen(password));
-				xfree(password);
-			}
-			
 			return;
 		}
 
 		if (attempt > AUTH_FAIL_MAX) {
-			/* Clean up */
 			if (client_user != NULL)
 				xfree(client_user);
 
-			if (password != NULL) {
-				memset(password, 0, strlen(password));
-				xfree(password);
-			}
-			
 			packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
 		}
 #endif /* HAVE_LIBPAM */
@@ -1785,6 +1788,12 @@
 
 			/* Indicate that we now have a pty. */
 			have_pty = 1;
+
+#ifdef HAVE_LIBPAM
+			/* do the pam_open_session since we have the pty */
+			do_pam_session(pw->pw_name,ttyname);
+#endif /* HAVE_LIBPAM */
+
 			break;
 
 		case SSH_CMSG_X11_REQUEST_FORWARDING: