Index: TODO
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/TODO,v
retrieving revision 1.53
diff -u -r1.53 TODO
--- TODO	12 Jan 2003 23:00:34 -0000	1.53
+++ TODO	14 Jan 2003 09:18:01 -0000
@@ -15,8 +15,6 @@
 
 - More platforms for for setproctitle() emulation (testing needed)
 
-- Handle changing passwords for the non-PAM expired password case
-
 - Improve PAM support (a pam_lastlog module will cause sshd to exit)
   and maybe support alternate forms of authentications like OPIE via
   pam?
Index: acconfig.h
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/acconfig.h,v
retrieving revision 1.149
diff -u -r1.149 acconfig.h
--- acconfig.h	10 Mar 2003 00:38:10 -0000	1.149
+++ acconfig.h	26 Mar 2003 03:13:05 -0000
@@ -25,6 +25,9 @@
 /* from environment and PATH */
 #undef LOGIN_PROGRAM_FALLBACK
 
+/* Path to passwd program */
+#undef PASSWD_PROGRAM_PATH
+
 /* Define if your password has a pw_class field */
 #undef HAVE_PW_CLASS_IN_PASSWD
 
Index: auth-pam.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth-pam.c,v
retrieving revision 1.57
diff -u -r1.57 auth-pam.c
--- auth-pam.c	29 Apr 2003 13:22:40 -0000	1.57
+++ auth-pam.c	30 Apr 2003 01:56:07 -0000
@@ -42,8 +42,6 @@
 
 #define NEW_AUTHTOK_MSG \
 	"Warning: Your password has expired, please change it now."
-#define NEW_AUTHTOK_MSG_PRIVSEP \
-	"Your password has expired, the session cannot proceed."
 
 static int do_pam_conversation(int num_msg, const struct pam_message **msg,
 	struct pam_response **resp, void *appdata_ptr);
@@ -60,7 +58,7 @@
 /* states for do_pam_conversation() */
 enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN;
 /* remember whether pam_acct_mgmt() returned PAM_NEW_AUTHTOK_REQD */
-static int password_change_required = 0;
+extern int password_change_required;
 /* remember whether the last pam_authenticate() succeeded or not */
 static int was_authenticated = 0;
 
@@ -248,18 +246,10 @@
 		case PAM_SUCCESS:
 			/* This is what we want */
 			break;
-#if 0
 		case PAM_NEW_AUTHTOK_REQD:
-			message_cat(&__pam_msg, use_privsep ?
-			    NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG);
-			/* flag that password change is necessary */
-			password_change_required = 1;
-			/* disallow other functionality for now */
-			no_port_forwarding_flag |= 2;
-			no_agent_forwarding_flag |= 2;
-			no_x11_forwarding_flag |= 2;
+			message_cat(&__pam_msg, NEW_AUTHTOK_MSG);
+			flag_password_change_required();
 			break;
-#endif
 		default:
 			logit("PAM rejected by account configuration[%d]: "
 			    "%.200s", pam_retval, PAM_STRERROR(__pamh, 
@@ -345,13 +335,7 @@
 			fatal("PAM pam_chauthtok failed[%d]: %.200s",
 			    pam_retval, PAM_STRERROR(__pamh, pam_retval));
 #if 0
-		/* XXX: This would need to be done in the parent process,
-		 * but there's currently no way to pass such request. */
-		no_port_forwarding_flag &= ~2;
-		no_agent_forwarding_flag &= ~2;
-		no_x11_forwarding_flag &= ~2;
-		if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
-			channel_permit_all_opens();
+		flag_password_change_successful();
 #endif
 	}
 }
Index: auth-passwd.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth-passwd.c,v
retrieving revision 1.52
diff -u -r1.52 auth-passwd.c
--- auth-passwd.c	29 Apr 2003 13:22:40 -0000	1.52
+++ auth-passwd.c	30 Apr 2003 13:20:55 -0000
@@ -42,6 +42,10 @@
 #include "log.h"
 #include "servconf.h"
 #include "auth.h"
+#include "buffer.h"
+#include "misc.h"
+#include "channels.h"
+#include "auth-options.h"
 
 #if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
 /* Don't need any of these headers for the PAM or SIA cases */
@@ -81,9 +85,8 @@
 #endif /* !USE_PAM && !HAVE_OSF_SIA */
 
 extern ServerOptions options;
-#ifdef WITH_AIXAUTHENTICATE
-extern char *aixloginmsg;
-#endif
+
+int password_change_required = 0;
 
 /*
  * Tries to authenticate the user using password.  Returns true if
@@ -153,15 +156,16 @@
 # endif
 # ifdef WITH_AIXAUTHENTICATE
 	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
-
+	aix_remove_embedded_newlines(authmsg);
 	if (authsuccess)
-	        /* We don't have a pty yet, so just label the line as "ssh" */
-	        if (loginsuccess(authctxt->user,
-			get_canonical_hostname(options.verify_reverse_mapping),
-			"ssh", &aixloginmsg) < 0)
-				aixloginmsg = NULL;
-
-	return(authsuccess);
+		debug3("AIX/authenticate succeeded for user %s: %.100s",
+		    pw->pw_name, authmsg);
+	else
+		debug3("AIX/authenticate failed for user %s: %.100s",
+		    pw->pw_name, authmsg);
+	if (authmsg)
+		xfree(authmsg);
+	return authsuccess;
 # endif
 # ifdef KRB4
 	if (options.kerberos_authentication == 1) {
@@ -236,4 +240,79 @@
 	/* Authentication is accepted if the encrypted passwords are identical. */
 	return (strcmp(encrypted_password, pw_password) == 0);
 #endif /* !USE_PAM && !HAVE_OSF_SIA */
+}
+
+/*
+ * Perform generic password change via tty. Like do_pam_chauthtok(),
+ * it throws a fatal error if the password can't be changed.
+ */
+int
+do_tty_change_password(struct passwd *pw)
+{
+	pid_t pid;
+	int status;
+	mysig_t old_signal;
+
+	old_signal = mysignal(SIGCHLD, SIG_DFL);
+
+	if ((pid = fork()) == -1)
+		fatal("Couldn't fork: %s", strerror(errno));
+
+	if (pid == 0) {
+		setuid(pw->pw_uid);
+		if (geteuid() == 0) 
+			execl(PASSWD_PROGRAM_PATH, "passwd", pw->pw_name,
+			    (char *)NULL);
+		else
+			execl(PASSWD_PROGRAM_PATH, "passwd", (char *)NULL);
+			
+		/* execl shouldn't return */
+		fatal("Couldn't exec %s", PASSWD_PROGRAM_PATH);
+		exit(1);
+	}
+
+	if (waitpid(pid, &status, 0) == -1)
+		fatal("Couldn't wait for child: %s", strerror(errno));
+	mysignal(SIGCHLD, old_signal);
+
+	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+		debug("%s password changed sucessfully", __func__);
+		flag_password_change_successful();
+		return 1;
+	} else {
+		fatal("Failed to change password for %s, passwd returned %d",
+		    pw->pw_name, status);
+		return 0;
+	}
+}
+
+/*
+ * flag that password change is necessary
+ */
+void
+flag_password_change_required(void)
+{
+	debug3("disabling forwarding");
+	password_change_required = 1;
+
+	/* disallow other functionality for now */
+	no_port_forwarding_flag |= 2;
+	no_agent_forwarding_flag |= 2;
+	no_x11_forwarding_flag |= 2;
+}
+
+/*
+ * password change successful
+ * XXX: must be done in parent, but currently there is no way to pass
+ * this request.
+ */
+void
+flag_password_change_successful(void)
+{
+	debug3("resetting forwarding flags");
+
+	password_change_required = 0;
+	no_port_forwarding_flag &= ~2;
+	no_agent_forwarding_flag &= ~2;
+	no_x11_forwarding_flag &= ~2;
 }
Index: auth.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth.c,v
retrieving revision 1.69
diff -u -r1.69 auth.c
--- auth.c	9 Apr 2003 11:12:00 -0000	1.69
+++ auth.c	30 Apr 2003 13:58:30 -0000
@@ -36,6 +36,11 @@
 #include <libgen.h>
 #endif
 
+#ifdef WITH_AIXAUTHENTICATE
+#include <userpw.h>
+#include <usersec.h>
+#endif
+
 #include "xmalloc.h"
 #include "match.h"
 #include "groupaccess.h"
@@ -51,9 +56,12 @@
 #include "misc.h"
 #include "bufaux.h"
 #include "packet.h"
+#include "sshlogin.h"
 
 /* import */
 extern ServerOptions options;
+extern Buffer expire_message;
+extern Buffer login_message;
 
 /* Debugging messages */
 Buffer auth_debug;
@@ -75,9 +83,6 @@
 	const char *hostname = NULL, *ipaddr = NULL;
 	char *shell;
 	int i;
-#ifdef WITH_AIXAUTHENTICATE
-	char *loginmsg;
-#endif /* WITH_AIXAUTHENTICATE */
 #if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
     !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
 	struct spwd *spw;
@@ -88,35 +93,63 @@
 	if (!pw || !pw->pw_name)
 		return 0;
 
+#define	DAY		(24L * 60 * 60) /* 1 day in seconds */
+#define WEEK		(DAY * 7)	/* 1 week in seconds */
 #if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
     !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
-#define	DAY		(24L * 60 * 60) /* 1 day in seconds */
 	if ((spw = getspnam(pw->pw_name)) != NULL) {
+		int daysleft;
+
 		today = time(NULL) / DAY;
 		debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
-		    " sp_max %d", (int)today, (int)spw->sp_expire,
-		    (int)spw->sp_lstchg, (int)spw->sp_max);
+		    " sp_max %d sp_warn %d", (int)today, (int)spw->sp_expire,
+		    (int)spw->sp_lstchg, (int)spw->sp_max, (int)spw->sp_warn);
 
 		/*
 		 * We assume account and password expiration occurs the
 		 * day after the day specified.
 		 */
-		if (spw->sp_expire != -1 && today > spw->sp_expire) {
+		daysleft = spw->sp_expire - today;
+		if (spw->sp_expire == -1) {
+			debug3("account expiration disabled");
+		} else if (today > spw->sp_expire) {
 			logit("Account %.100s has expired", pw->pw_name);
 			return 0;
-		}
+		} else if (daysleft <= spw->sp_warn) {
+			char buf[256];
 
+			debug3("account will expire in %d days", daysleft);
+			snprintf(buf, sizeof(buf),
+			    "Your account will expire in %d day%s.\n",
+			    daysleft, daysleft == 1 ? "" : "s");
+			buffer_append(&login_message, buf, strlen(buf));
+		}
+		
+#define PWCHG_FORCED    "You must change your password now.\n"
+#define PWCHG_EXPIRED   "Your password has expired, you must change it now.\n"
+		daysleft = spw->sp_lstchg + spw->sp_max - today;
 		if (spw->sp_lstchg == 0) {
 			logit("User %.100s password has expired (root forced)",
 			    pw->pw_name);
-			return 0;
-		}
-
-		if (spw->sp_max != -1 &&
-		    today > spw->sp_lstchg + spw->sp_max) {
+			flag_password_change_required();
+			buffer_append(&expire_message, PWCHG_FORCED,
+			    sizeof(PWCHG_FORCED));
+		} else if (spw->sp_max == -1) {
+			debug3("password expiration disabled");
+		} else if (daysleft < 0) {
 			logit("User %.100s password has expired (password aged)",
 			    pw->pw_name);
-			return 0;
+			flag_password_change_required();
+			buffer_append(&expire_message, PWCHG_EXPIRED,
+			    sizeof(PWCHG_EXPIRED));
+		} else if (daysleft <= spw->sp_warn) {
+			char buf[256];
+
+			debug3("password will expire in %d days", daysleft);
+			snprintf(buf, sizeof(buf),
+			    "Your password will expire in %d day%s.\n",
+			    daysleft, daysleft == 1 ? "" : "s");
+			buffer_append(&expire_message, buf, strlen(buf));
 		}
 	}
 #endif
@@ -206,26 +239,79 @@
 	 * PermitRootLogin to control logins via ssh), or if running as
 	 * non-root user (since loginrestrictions will always fail).
 	 */
-	if ((pw->pw_uid != 0) && (geteuid() == 0) &&
-	    loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
+	if ( (pw->pw_uid != 0) && (geteuid() == 0) ) {
 		int loginrestrict_errno = errno;
+		char *msg;
 
-		if (loginmsg && *loginmsg) {
-			/* Remove embedded newlines (if any) */
-			char *p;
-			for (p = loginmsg; *p; p++) {
-				if (*p == '\n')
-					*p = ' ';
+		/* check for AIX account restrictions */
+		if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg) != 0) {
+			if (msg && *msg) {
+				aix_remove_embedded_newlines(msg);
+				log("Login restricted for %s: %.100s",
+				    pw->pw_name, msg);
+				xfree(msg);
 			}
-			/* Remove trailing newline */
-			*--p = '\0';
-			logit("Login restricted for %s: %.100s", pw->pw_name, 
-			    loginmsg);
-		}
-		/* Don't fail if /etc/nologin  set */
-	    	if (!(loginrestrict_errno == EPERM && 
-		    stat(_PATH_NOLOGIN, &st) == 0))
-			return 0;
+
+			/* Don't fail if /etc/nologin  set */
+			if (!(loginrestrict_errno == EPERM &&
+			    stat(_PATH_NOLOGIN, &st) == 0))
+				return 0;
+		}
+	}
+
+
+	/*
+	 * Check AIX password expiry.  Only check when running as root.
+	 * Unpriv'ed users can't access /etc/security/passwd or
+	 * /etc/security/user so passwdexpired will always fail.
+	 */
+	if (geteuid() == 0) {
+		char *msg, *user = pw->pw_name;
+		int result, maxage, result2, maxexpired;
+		struct userpw *upw;
+
+		/* Check if password expired too long as in this case,
+		 * passwdexpired still returns 1 but /bin/passwd will fail */
+		upw = getuserpw(user);
+		result = getuserattr(user, S_MAXEXPIRED, &maxexpired, SEC_INT);
+		result2 = getuserattr(user, S_MAXAGE, &maxage, SEC_INT);
+		if (upw != NULL && result == 0 && result2 == 0) {
+			time_t now = time(NULL);
+
+			debug3("%s lastupdate %lu maxage %d wks maxexpired %d"
+			    "wks time now %d", __func__, upw->upw_lastupdate,
+			    maxage, maxexpired, now);
+
+			if (maxexpired != -1 && maxage != 0 &&
+		       	    upw->upw_lastupdate + ((maxage+maxexpired) * WEEK) <= now ){
+				log("User %.100s password expired too long",
+				    user);
+				return 0;
+			}
+		}
+
+		result = passwdexpired(user, &msg);
+		if (msg && *msg) {
+			aix_remove_embedded_newlines(msg);
+			buffer_append(&expire_message, msg, strlen(msg));
+		}
+		debug3("AIX/passwdexpired returned %d msg %.100s", result, msg);
+
+		switch (result) {
+			case 0: /* success, password not expired */
+				break;
+			case 1: /* expired, password change required */
+				flag_password_change_required();
+				break;
+			default: /* user can't change(2) or other error (-1) */
+				logit("Password can't be changed for user %s: "
+				    "%.100s", user, msg);
+				if (msg)
+					xfree(msg);
+				return 0;
+		}
+		if (msg)
+			xfree(msg);
 	}
 #endif /* WITH_AIXAUTHENTICATE */
 
@@ -241,6 +327,45 @@
 	return authctxt;
 }
 
+/*
+ * Generate last_login message and store for later display.  This must be
+ * called before login_login() is called and lastlog is updated.
+ */
+void
+generate_login_message(const char *user, uid_t uid, const char *host)
+{
+#ifdef WITH_AIXAUTHENTICATE
+	char *msg;
+
+	/* We don't have a pty yet, so just label the line as "ssh" */
+	if (loginsuccess(user, host, "ssh", &msg) >= 0)
+		buffer_append(&login_message, msg, strlen(msg));
+#elif !defined(NO_SSH_LASTLOG)
+	if (options.print_lastlog) {
+		char *time_string, lasthost[MAXHOSTNAMELEN], buf[256];
+		time_t last_login_time;
+
+		last_login_time = get_last_login_time(uid, user, lasthost,
+		   sizeof(lasthost));
+
+		if (last_login_time != 0) {
+		       time_string = ctime(&last_login_time);
+		       if (strchr(time_string, '\n'))
+			       *strchr(time_string, '\n') = 0;
+		       if (strcmp(lasthost, "") == 0)
+			       snprintf(buf, sizeof(buf),
+				   "Last login: %s\r\n",
+				   time_string);
+		       else
+			       snprintf(buf, sizeof(buf),
+				   "Last login: %s from %s\r\n",
+				   time_string, lasthost);
+		       buffer_append(&login_message, buf, strlen(buf));
+		}
+       }
+#endif
+}
+
 void
 auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
 {
@@ -268,6 +393,9 @@
 	    get_remote_port(),
 	    info);
 
+	if (authenticated && geteuid() == 0)
+		generate_login_message(authctxt->user, authctxt->pw->pw_uid,
+		    get_canonical_hostname(options.verify_reverse_mapping));
 #ifdef WITH_AIXAUTHENTICATE
 	if (authenticated == 0 && strcmp(method, "password") == 0)
 	    loginfailed(authctxt->user,
Index: auth.h
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth.h,v
retrieving revision 1.44
diff -u -r1.44 auth.h
--- auth.h	27 Sep 2002 03:26:01 -0000	1.44
+++ auth.h	12 Mar 2003 08:25:57 -0000
@@ -156,6 +156,9 @@
 
 int	allowed_user(struct passwd *);
 struct passwd * getpwnamallow(const char *user);
+int	do_tty_change_password(struct passwd *pw);
+void	flag_password_change_required(void);
+void	flag_password_change_successful(void);
 
 char	*get_challenge(Authctxt *);
 int	verify_response(Authctxt *, const char *);
Index: configure.ac
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/configure.ac,v
retrieving revision 1.114
diff -u -r1.114 configure.ac
--- configure.ac	29 Apr 2003 13:22:40 -0000	1.114
+++ configure.ac	30 Apr 2003 01:56:16 -0000
@@ -41,6 +41,13 @@
 	fi
 fi
 
+AC_PATH_PROG(PASSWD_PROGRAM_PATH, passwd)
+if test ! -z "$PASSWD_PROGRAM_PATH" ; then
+	AC_DEFINE_UNQUOTED(PASSWD_PROGRAM_PATH, "$PASSWD_PROGRAM_PATH")
+else
+	AC_MSG_ERROR([*** passwd command not found - check config.log ***])
+fi
+
 if test -z "$LD" ; then
 	LD=$CC
 fi
Index: session.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/session.c,v
retrieving revision 1.233
diff -u -r1.233 session.c
--- session.c	9 Apr 2003 10:59:50 -0000	1.233
+++ session.c	28 Apr 2003 05:11:34 -0000
@@ -95,6 +95,9 @@
 extern u_int utmp_len;
 extern int startup_pipe;
 extern void destroy_sensitive_data(void);
+extern Buffer expire_message;
+extern Buffer login_message;
+extern int password_change_required;
 
 /* original command from peer. */
 const char *original_command = NULL;
@@ -103,10 +106,6 @@
 #define MAX_SESSIONS 10
 Session	sessions[MAX_SESSIONS];
 
-#ifdef WITH_AIXAUTHENTICATE
-char *aixloginmsg;
-#endif /* WITH_AIXAUTHENTICATE */
-
 #ifdef HAVE_LOGIN_CAP
 login_cap_t *lc;
 #endif
@@ -458,10 +457,11 @@
 #if defined(USE_PAM)
 	do_pam_session(s->pw->pw_name, NULL);
 	do_pam_setcred(1);
-	if (is_pam_password_change_required())
+#endif /* USE_PAM */
+
+	if (password_change_required)
 		packet_disconnect("Password change required but no "
 		    "TTY available");
-#endif /* USE_PAM */
 
 	/* Fork the child. */
 	if ((pid = fork()) == 0) {
@@ -721,10 +721,10 @@
 void
 do_login(Session *s, const char *command)
 {
-	char *time_string;
 	socklen_t fromlen;
 	struct sockaddr_storage from;
 	struct passwd * pw = s->pw;
+	int password_changed = 0;
 	pid_t pid = getpid();
 
 	/*
@@ -748,41 +748,39 @@
 		    options.verify_reverse_mapping),
 		    (struct sockaddr *)&from, fromlen);
 
-#ifdef USE_PAM
 	/*
 	 * If password change is needed, do it now.
 	 * This needs to occur before the ~/.hushlogin check.
 	 */
-	if (is_pam_password_change_required()) {
+	buffer_append(&expire_message, "\0", 1);
+	if (password_change_required) {
+#ifdef USE_PAM
 		print_pam_messages();
-		do_pam_chauthtok();
-	}
+		if (use_privsep)
+			do_pam_chauthtok();
+		else
+			do_tty_change_password(pw);
+#else
+		printf("%s", (char *)buffer_ptr(&expire_message));
+		do_tty_change_password(pw);
 #endif
+		password_changed = 1;
+	}
 
 	if (check_quietlogin(s, command))
 		return;
 
+	if (!password_changed) {
 #ifdef USE_PAM
-	if (!is_pam_password_change_required())
 		print_pam_messages();
+#else
+		printf("%s", (char *)buffer_ptr(&expire_message));
 #endif /* USE_PAM */
-#ifdef WITH_AIXAUTHENTICATE
-	if (aixloginmsg && *aixloginmsg)
-		printf("%s\n", aixloginmsg);
-#endif /* WITH_AIXAUTHENTICATE */
-
-#ifndef NO_SSH_LASTLOG
-	if (options.print_lastlog && s->last_login_time != 0) {
-		time_string = ctime(&s->last_login_time);
-		if (strchr(time_string, '\n'))
-			*strchr(time_string, '\n') = 0;
-		if (strcmp(s->hostname, "") == 0)
-			printf("Last login: %s\r\n", time_string);
-		else
-			printf("Last login: %s from %s\r\n", time_string,
-			    s->hostname);
 	}
-#endif /* NO_SSH_LASTLOG */
+
+	/* display post-login message */
+	buffer_append(&login_message, "\0", 1);
+	printf("%s", (char *)buffer_ptr(&login_message));
 
 	do_motd();
 }
@@ -1603,12 +1601,6 @@
 	if (s->ttyfd != -1) {
 		packet_disconnect("Protocol error: you already have a pty.");
 		return 0;
-	}
-	/* Get the time and hostname when the user last logged in. */
-	if (options.print_lastlog) {
-		s->hostname[0] = '\0';
-		s->last_login_time = get_last_login_time(s->pw->pw_uid,
-		    s->pw->pw_name, s->hostname, sizeof(s->hostname));
 	}
 
 	s->term = packet_get_string(&len);
Index: session.h
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/session.h,v
retrieving revision 1.23
diff -u -r1.23 session.h
--- session.h	4 Jul 2002 00:14:18 -0000	1.23
+++ session.h	1 Feb 2003 07:22:08 -0000
@@ -39,9 +39,6 @@
 	int	ptyfd, ttyfd, ptymaster;
 	u_int	row, col, xpixel, ypixel;
 	char	tty[TTYSZ];
-	/* last login */
-	char	hostname[MAXHOSTNAMELEN];
-	time_t	last_login_time;
 	/* X11 */
 	u_int	display_number;
 	char	*display;
Index: sshd.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/sshd.c,v
retrieving revision 1.237
diff -u -r1.237 sshd.c
--- sshd.c	9 Apr 2003 10:59:50 -0000	1.237
+++ sshd.c	28 Apr 2003 05:11:49 -0000
@@ -205,6 +205,9 @@
 int use_privsep;
 struct monitor *pmonitor;
 
+Buffer expire_message; /* "password will expire/has expired" messages */
+Buffer login_message;  /* message to be displayed after login */
+
 /* Prototypes for various functions defined later in this file. */
 void destroy_sensitive_data(void);
 void demote_sensitive_data(void);
@@ -1505,6 +1508,10 @@
 	if (use_privsep)
 		if ((authctxt = privsep_preauth()) != NULL)
 			goto authenticated;
+
+	/* prepare buffers to collect authentication/expiry messages */
+	buffer_init(&login_message);
+	buffer_init(&expire_message);
 
 	/* perform the key exchange */
 	/* authenticate user and start session */
Index: version.h
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/version.h,v
retrieving revision 1.44
diff -u -r1.44 version.h
--- version.h	29 Apr 2003 13:22:40 -0000	1.44
+++ version.h	30 Apr 2003 01:58:58 -0000
@@ -1,3 +1,3 @@
 /* $OpenBSD: version.h,v 1.37 2003/04/01 10:56:46 markus Exp $ */
 
-#define SSH_VERSION    "OpenSSH_3.6.1p2"
+#define SSH_VERSION    "OpenSSH_3.6.1p2-pwexp19"
Index: openbsd-compat/port-aix.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/openbsd-compat/port-aix.c,v
retrieving revision 1.6
diff -u -r1.6 port-aix.c
--- openbsd-compat/port-aix.c	7 Jul 2002 02:17:36 -0000	1.6
+++ openbsd-compat/port-aix.c	14 Jan 2003 22:14:22 -0000
@@ -52,5 +52,25 @@
 	xfree(cp);
 }
 
-#endif /* _AIX */
+#ifdef WITH_AIXAUTHENTICATE
+/*
+ * Remove embedded newlines in string (if any).
+ * Used before logging messages returned by AIX authentication functions
+ * so the message is logged on one line.
+ */
+void
+aix_remove_embedded_newlines(char *p)
+{
+	if (p == NULL)
+		return;
+
+	for (; *p; p++) {
+		if (*p == '\n')
+			*p = ' ';
+	}
+	/* Remove trailing newline */
+	*--p = '\0';
+}
+#endif /* WITH_AIXAUTHENTICATE */
 
+#endif /* _AIX */
Index: openbsd-compat/port-aix.h
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/openbsd-compat/port-aix.h,v
retrieving revision 1.7
diff -u -r1.7 port-aix.h
--- openbsd-compat/port-aix.h	1 Feb 2003 04:43:35 -0000	1.7
+++ openbsd-compat/port-aix.h	1 Feb 2003 05:45:45 -0000
@@ -37,4 +37,5 @@
 #endif
 
 void aix_usrinfo(struct passwd *pw);
+void aix_remove_embedded_newlines(char *);
 #endif /* _AIX */
