diff -ru openssh-3.5p1.orig/auth-passwd.c openssh-3.5p1/auth-passwd.c --- openssh-3.5p1.orig/auth-passwd.c Thu Sep 26 09:14:16 2002 +++ openssh-3.5p1/auth-passwd.c Sat Oct 19 14:59:26 2002 @@ -82,6 +82,7 @@ extern ServerOptions options; #ifdef WITH_AIXAUTHENTICATE +void aix_remove_embedded_newlines(char *); extern char *aixloginmsg; #endif @@ -149,13 +150,20 @@ #endif #ifdef WITH_AIXAUTHENTICATE authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0); + aix_remove_embedded_newlines(authmsg); - if (authsuccess) + if (authsuccess) { + debug("authenticate() succeeded for user %s: %.100s", pw->pw_name, authmsg); /* 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; + } else { + debug("authenticate() failed for user %s: %.100s", pw->pw_name, authmsg); + } + if (authmsg) + xfree(authmsg); return(authsuccess); #endif diff -ru openssh-3.5p1.orig/auth.c openssh-3.5p1/auth.c --- openssh-3.5p1.orig/auth.c Sun Sep 22 01:26:53 2002 +++ openssh-3.5p1/auth.c Sat Oct 19 15:49:22 2002 @@ -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 @@ -75,9 +81,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; @@ -202,19 +205,47 @@ } #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) ) { + char *restrictmsg, *expiremsg; + int passexpcode; + + /* check for AIX account restrictions */ + if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &restrictmsg) != 0) { + if (restrictmsg && *restrictmsg) { + aix_remove_embedded_newlines(restrictmsg); + log("Login restricted for %s: %.100s", pw->pw_name, restrictmsg); + xfree(restrictmsg); } - /* Remove trailing newline */ - *--p = '\0'; - log("Login restricted for %s: %.100s", pw->pw_name, loginmsg); + return 0; + } + + /* check for AIX expired account */ + passexpcode = passwdexpired(pw->pw_name, &aixexpiremsg); + + switch (passexpcode) { + case 0: /* success, password not expired */ + break; + case 1: /* expired, password change required */ + aix_password_change_required = 1; + break; + default: /* expired too long (2) or other error (-1) */ + /* make local copy of message and remove newlines for logging */ + if (aixexpiremsg && *aixexpiremsg) { + expiremsg = xstrdup(aixexpiremsg); + aix_remove_embedded_newlines(expiremsg); + } + debug("passwdexpired() returned %d", passexpcode); + log("Password expired too long or system failure for user %s: %.100s", + pw->pw_name, expiremsg); + if (expiremsg) + xfree(expiremsg); + return 0; } - return 0; } #endif /* WITH_AIXAUTHENTICATE */ diff -ru openssh-3.5p1.orig/openbsd-compat/port-aix.c openssh-3.5p1/openbsd-compat/port-aix.c --- openssh-3.5p1.orig/openbsd-compat/port-aix.c Sun Jul 7 12:17:36 2002 +++ openssh-3.5p1/openbsd-compat/port-aix.c Sat Oct 19 15:02:26 2002 @@ -24,6 +24,7 @@ * */ #include "includes.h" +#include "misc.h" #ifdef _AIX @@ -52,5 +53,60 @@ 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'; +} + +/* + * Perform password change on AIX + * Like do_pam_chauthtok(), it throws a fatal error if the password can't be changed. + */ +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); + /* execl shouldn't return */ + fatal("Couldn't exec /usr/bin/passwd"); + exit(1); + } + + if (waitpid(pid, &status, 0) == -1) + fatal("Couldn't wait for child: %s", strerror(errno)); + if (WEXITSTATUS(status)) /* Passwd exited abnormally */ + fatal("Failed to change password for %s, passwd returned %d", pw->pw_name, status); + + mysignal(SIGCHLD, old_signal); +} +#endif /* WITH_AIXAUTHENTICATE */ + +#endif /* _AIX */ diff -ru openssh-3.5p1.orig/session.c openssh-3.5p1/session.c --- openssh-3.5p1.orig/session.c Thu Sep 26 10:38:50 2002 +++ openssh-3.5p1/session.c Sat Oct 19 15:11:06 2002 @@ -104,7 +104,10 @@ Session sessions[MAX_SESSIONS]; #ifdef WITH_AIXAUTHENTICATE +void do_aix_change_password(struct passwd *); char *aixloginmsg; +char *aixexpiremsg; +int aix_password_change_required = 0; #endif /* WITH_AIXAUTHENTICATE */ #ifdef HAVE_LOGIN_CAP @@ -461,6 +464,12 @@ "TTY available"); #endif /* USE_PAM */ +#ifdef WITH_AIXAUTHENTICATE + if (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 (aix_password_change_required) { + printf("%s\n", aixexpiremsg); + do_aix_change_password(pw); + } +#endif + if (check_quietlogin(s, command)) return; @@ -764,9 +780,17 @@ if (!is_pam_password_change_required()) print_pam_messages(); #endif /* USE_PAM */ + #ifdef WITH_AIXAUTHENTICATE - if (aixloginmsg && *aixloginmsg) + if (aixexpiremsg && *aixexpiremsg) { + if (!aix_password_change_required) + printf("%s\n", aixexpiremsg); + xfree(aixexpiremsg); + } + if (aixloginmsg && *aixloginmsg) { printf("%s\n", aixloginmsg); + xfree(aixloginmsg); + } #endif /* WITH_AIXAUTHENTICATE */ #ifndef NO_SSH_LASTLOG