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 #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 */