Index: auth.c
===================================================================
RCS file: /cvs/openssh/auth.c,v
retrieving revision 1.58
diff -u -r1.58 auth.c
--- auth.c	21 Sep 2002 15:26:53 -0000	1.58
+++ auth.c	13 Oct 2002 11:06:27 -0000
@@ -59,6 +59,12 @@
 Buffer auth_debug;
 int auth_debug_init;
 
+#ifdef WITH_AIXAUTHENTICATE
+void aix_remove_embedded_newlines(char *);
+extern char *aixexpiremsg;
+extern int aix_password_change_required;
+#endif
+
 /*
  * Check if the user is allowed to log in via ssh. If user is listed
  * in DenyUsers or one of user's groups is listed in DenyGroups, false
@@ -202,19 +208,39 @@
 	}
 
 #ifdef WITH_AIXAUTHENTICATE
-	if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
-		if (loginmsg && *loginmsg) {
-			/* Remove embedded newlines (if any) */
-			char *p;
-			for (p = loginmsg; *p; p++) {
-				if (*p == '\n')
-					*p = ' ';
+	/*
+	 * Don't check loginrestrictions or expiry for root account (use
+	 * 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) ) {
+		int passexpcode;
+
+		/* check for AIX account restrictions */
+		if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
+			if (loginmsg && *loginmsg) {
+				aix_remove_embedded_newlines(loginmsg);
+				log("Login restricted for %s: %.100s", pw->pw_name, loginmsg);
 			}
-			/* Remove trailing newline */
-			*--p = '\0';
-			log("Login restricted for %s: %.100s", pw->pw_name, loginmsg);
+			return 0;
 		}
-		return 0;
+
+		/* check for AIX expired account */
+		passexpcode = passwdexpired(pw->pw_name, &aixexpiremsg);
+		if ( passexpcode  > 0 ) {
+			if (aixexpiremsg && *aixexpiremsg) {
+				aix_remove_embedded_newlines(aixexpiremsg);
+					
+				if ( passexpcode == 1 ) {
+					aix_password_change_required = 1;
+				} else {
+					/* expired too long, account locked */
+					log("Password expired too long or system failure %s: %.100s",
+					     pw->pw_name, aixexpiremsg);
+					return 0;
+				}
+			}
+              }
 	}
 #endif /* WITH_AIXAUTHENTICATE */
 
Index: session.c
===================================================================
RCS file: /cvs/openssh/session.c,v
retrieving revision 1.222
diff -u -r1.222 session.c
--- session.c	26 Sep 2002 00:38:50 -0000	1.222
+++ session.c	13 Oct 2002 11:06:28 -0000
@@ -104,7 +104,10 @@
 Session	sessions[MAX_SESSIONS];
 
 #ifdef WITH_AIXAUTHENTICATE
+int is_aix_password_change_required(void);
+void do_aix_change_password(struct passwd *);
 char *aixloginmsg;
+char *aixexpiremsg;
 #endif /* WITH_AIXAUTHENTICATE */
 
 #ifdef HAVE_LOGIN_CAP
@@ -461,6 +464,12 @@
 		    "TTY available");
 #endif /* USE_PAM */
 
+#ifdef WITH_AIXAUTHENTICATE
+	if (is_aix_password_change_required())
+		packet_disconnect("Password change required but no "
+		    "TTY available");
+#endif /* WITH_AIXAUTHENTICATE */
+
 	/* Fork the child. */
 	if ((pid = fork()) == 0) {
 		fatal_remove_all_cleanups();
@@ -757,6 +766,13 @@
 	}
 #endif
 
+#ifdef WITH_AIXAUTHENTICATE
+	if (is_aix_password_change_required()) {
+		printf("%s\n", aixexpiremsg);
+		do_aix_change_password(pw);
+	}
+#endif
+
 	if (check_quietlogin(s, command))
 		return;
 
@@ -764,7 +780,10 @@
 	if (!is_pam_password_change_required())
 		print_pam_messages();
 #endif /* USE_PAM */
+
 #ifdef WITH_AIXAUTHENTICATE
+	if (!is_aix_password_change_required() && aixexpiremsg && *aixexpiremsg)
+		printf("%s\n", aixexpiremsg);
 	if (aixloginmsg && *aixloginmsg)
 		printf("%s\n", aixloginmsg);
 #endif /* WITH_AIXAUTHENTICATE */
Index: openbsd-compat/port-aix.c
===================================================================
RCS file: /cvs/openssh/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	13 Oct 2002 11:06:28 -0000
@@ -27,6 +27,11 @@
 
 #ifdef _AIX
 
+#ifdef WITH_AIXAUTHENTICATE
+#include "misc.h"
+int aix_password_change_required=0;
+#endif /* WITH_AIX_AUTHENTICATE */
+
 #include <uinfo.h>
 #include <../xmalloc.h>
 
@@ -52,5 +57,53 @@
 	xfree(cp);
 }
 
-#endif /* _AIX */
+#ifdef WITH_AIXAUTHENTICATE
+/* Remove embedded newlines (if any) */
+void
+aix_remove_embedded_newlines(char *p)
+{
+	for (; *p; p++) {
+		if (*p == '\n')
+			*p = ' ';
+	}
+	/* Remove trailing newline */
+	*--p = '\0';
+}
+
+int
+is_aix_password_change_required(void)
+{
+	return aix_password_change_required;
+}
+
+void
+do_aix_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);
+		execl("/usr/bin/passwd","passwd",pw->pw_name,
+			(char *)NULL);
+	}
+
+	if (waitpid(pid, &status, 0) == -1)
+		fatal("Couldn't wait for child: %s", strerror(errno));
 
+	/* Passwd exited abnormally */
+
+	if (WEXITSTATUS(status)) 
+		exit(1);
+
+	mysignal(SIGCHLD, old_signal);
+}
+#endif /* WITH_AIXAUTHENTICATE */
+
+#endif /* _AIX */
