[PATCH] AIX password expiration (via passwd)
Darren Tucker
dtucker at zip.com.au
Wed Oct 30 23:34:39 EST 2002
Ben Lindstrom wrote:
> Forking off a connection to /usr/bin/passwd and writing a C script to
> automate changing password. I just think it will be a pain.
I'm not sure how this should be done, but I didn't let that stop me :-).
This patch is an experiment with allocating a pty, forking off
/usr/bin/passwd and changing the password via it for protocol 2. It's
stupidly simplistic.
It currently works on AIX without privsep. It core dumps with privsep
and I don't know why.
Is it worth persuing this or should I cut my losses and go back to
spawning passwd in the session for protocol 2?
Incidentally, the shadow password changing in patch #7 has been reported
to work on UnixWare 2.1.3 as-is (in addition to Solaris and Redhat
previously tested).
--
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69
Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.
-------------- next part --------------
diff -ru ../openssh-3.5p1.orig/auth-pam.c openssh-3.5p1-passexpire_pty/auth-pam.c
--- ../openssh-3.5p1.orig/auth-pam.c Mon Jul 29 06:24:08 2002
+++ openssh-3.5p1-passexpire_pty/auth-pam.c Tue Oct 29 23:10:35 2002
@@ -60,7 +60,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;
diff -ru ../openssh-3.5p1.orig/auth-passwd.c openssh-3.5p1-passexpire_pty/auth-passwd.c
--- ../openssh-3.5p1.orig/auth-passwd.c Thu Sep 26 09:14:16 2002
+++ openssh-3.5p1-passexpire_pty/auth-passwd.c Wed Oct 30 10:06:03 2002
@@ -42,6 +42,10 @@
#include "log.h"
#include "servconf.h"
#include "auth.h"
+#include "misc.h"
+#include "xmalloc.h"
+#include "monitor_wrap.h"
+#include "sshpty.h"
#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
/* Don't need any of these headers for the PAM or SIA cases */
@@ -81,13 +85,15 @@
#endif /* !USE_PAM && !HAVE_OSF_SIA */
extern ServerOptions options;
+extern int password_change_required;
#ifdef WITH_AIXAUTHENTICATE
extern char *aixloginmsg;
#endif
/*
- * Tries to authenticate the user using password. Returns true if
- * authentication succeeds.
+ * Tries to authenticate the user using password. Returns true (1) if
+ * authentication succeeds, (2) if authentication succeeds but password
+ * change required.
*/
int
auth_password(Authctxt *authctxt, const char *password)
@@ -149,14 +155,25 @@
#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);
+ debug("auth_password: authsuccess = %d", authsuccess);
+ if (authsuccess && password_change_required) {
+ return 2;
+ }
return(authsuccess);
#endif
#ifdef KRB4
@@ -230,6 +247,136 @@
#endif /* HAVE_MD5_PASSWORDS */
/* Authentication is accepted if the encrypted passwords are identical. */
- return (strcmp(encrypted_password, pw_password) == 0);
+ if (strcmp(encrypted_password, pw_password) == 0) {
+ if (password_change_required) {
+ debug("auth_password: password expired");
+ return 2;
+ } else {
+ debug("auth_password: not expired");
+ return 1;
+ }
+ }
+ return 0;
#endif /* !USE_PAM && !HAVE_OSF_SIA */
+}
+
+void
+expect_fd(int fd, char expected)
+{
+ char c = '\0', buf[1024];
+ int p = 0;
+
+ debug("%s: entering, looking for '%c'", __func__, expected);
+ while (c != expected && p < 1024) {
+ read(fd, &c, 1);
+ buf[p++] = c;
+ }
+ buf[p] = '\0';
+ debug("%s, received: %s", __func__, buf);
+}
+
+void
+send_fd(int fd, const char *string)
+{
+ char cr = '\r';
+
+ debug("%s: sending string.", __func__);
+ write(fd, string, strlen(string));
+ write(fd, &cr, 1);
+}
+
+/* password change for protocol 2 */
+int
+auth_change_password(Authctxt *authctxt, const char *opass, const char *npass)
+{
+ pid_t pid;
+ int ptyfd, ttyfd, status;
+ char tty[64];
+ mysig_t old_signal;
+
+ if (pty_allocate(&ptyfd, &ttyfd, tty, 64))
+ fatal("%s: couldn't allocate pty", __func__);
+
+ if ((pid = fork()) == 0) {
+ pty_make_controlling_tty(&ttyfd, tty);
+ setuid(authctxt->pw->pw_uid);
+ close(ptyfd);
+
+ if (dup2(ttyfd, 0) < 0)
+ error("dup2 stdin: %s", strerror(errno));
+ if (dup2(ttyfd, 1) < 0)
+ error("dup2 stdout: %s", strerror(errno));
+ if (dup2(ttyfd, 2) < 0)
+ error("dup2 stderr: %s", strerror(errno));
+
+ /* Close the extra descriptor for the pseudo tty. */
+ close(ttyfd);
+ signal(SIGPIPE, SIG_DFL);
+
+ execl("/usr/bin/passwd","passwd", (char *)NULL);
+ /* execl shouldn't return */
+ fatal("Couldn't exec /usr/bin/passwd");
+ exit(1);
+ }
+
+ expect_fd(ptyfd, ':');
+ send_fd(ptyfd, opass);
+ expect_fd(ptyfd, ':');
+ send_fd(ptyfd, npass);
+ expect_fd(ptyfd, ':');
+ send_fd(ptyfd, npass);
+ expect_fd(ptyfd, '\n');
+
+ if (waitpid(pid, &status, 0) == -1)
+ fatal("Couldn't wait for child: %s", strerror(errno));
+ debug("%s: passwd returned %d", __func__, status);
+
+ close(ttyfd);
+ close(ptyfd);
+ pty_release(tty);
+
+ mysignal(SIGCHLD, old_signal);
+
+ if (WEXITSTATUS(status)) /* Passwd exited abnormally */
+ return 0;
+ else
+ return 1;
+}
+
+
+/*
+ * generic password change routine. requires session established and tty
+ * alloced. Like do_pam_chauthtok(), it throws a fatal error if the password
+ * can't be changed.
+ */
+
+void
+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);
+ 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);
}
diff -ru ../openssh-3.5p1.orig/auth.c openssh-3.5p1-passexpire_pty/auth.c
--- ../openssh-3.5p1.orig/auth.c Sun Sep 22 01:26:53 2002
+++ openssh-3.5p1-passexpire_pty/auth.c Tue Oct 29 23:10:36 2002
@@ -59,6 +59,10 @@
Buffer auth_debug;
int auth_debug_init;
+/* Password change flag */
+int password_change_required = 0;
+char *password_expire_message = NULL;
+
/*
* 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 +79,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;
@@ -106,14 +107,18 @@
if (spw->sp_lstchg == 0) {
log("User %.100s password has expired (root forced)",
pw->pw_name);
- return 0;
+ password_change_required = 1;
+ password_expire_message =
+ xstrdup("Your password has expired (root forced)");
}
if (spw->sp_max != -1 &&
today > spw->sp_lstchg + spw->sp_max) {
log("User %.100s password has expired (password aged)",
pw->pw_name);
- return 0;
+ password_change_required = 1;
+ password_expire_message =
+ xstrdup("Your password has expired");
}
}
#else
@@ -202,19 +207,48 @@
}
#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, &password_expire_message);
+ debug("passwdexpired() returned %d", passexpcode);
+
+ switch (passexpcode) {
+ case 0: /* success, password not expired */
+ break;
+ case 1: /* expired, password change required */
+ 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 (password_expire_message && *password_expire_message) {
+ expiremsg = xstrdup(password_expire_message);
+ 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/auth.h openssh-3.5p1-passexpire_pty/auth.h
--- ../openssh-3.5p1.orig/auth.h Fri Sep 27 13:26:01 2002
+++ openssh-3.5p1-passexpire_pty/auth.h Tue Oct 29 23:10:36 2002
@@ -101,6 +101,10 @@
int auth_rhosts_rsa(struct passwd *, char *, Key *);
int auth_password(Authctxt *, const char *);
+int auth_change_password(Authctxt *, const char *, const char *);
+#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
+int shadow_change_password(struct passwd *, const char *, const char *);
+#endif
int auth_rsa(struct passwd *, BIGNUM *);
int auth_rsa_challenge_dialog(Key *);
BIGNUM *auth_rsa_generate_challenge(Key *);
diff -ru ../openssh-3.5p1.orig/auth2-passwd.c openssh-3.5p1-passexpire_pty/auth2-passwd.c
--- ../openssh-3.5p1.orig/auth2-passwd.c Fri Jun 7 06:27:56 2002
+++ openssh-3.5p1-passexpire_pty/auth2-passwd.c Tue Oct 29 23:10:37 2002
@@ -31,28 +31,50 @@
#include "auth.h"
#include "monitor_wrap.h"
#include "servconf.h"
+#include "ssh2.h"
/* import */
extern ServerOptions options;
+extern int password_change_required;
static int
userauth_passwd(Authctxt *authctxt)
{
- char *password;
+ char *password, *npassword;
int authenticated = 0;
int change;
- u_int len;
- change = packet_get_char();
- if (change)
- log("password change not supported");
+ u_int len, nlen;
+
+ change_requested = packet_get_char();
password = packet_get_string(&len);
+ if (change_requested) {
+ debug("%s: password change requested by client", __func__);
+ npassword = packet_get_string(&nlen);
+ }
packet_check_eom();
+
if (authctxt->valid &&
#ifdef HAVE_CYGWIN
- check_nt_auth(1, authctxt->pw) &&
+ check_nt_auth(1, authctxt->pw)
#endif
- PRIVSEP(auth_password(authctxt, password)) == 1)
- authenticated = 1;
+ )
+ authenticated = PRIVSEP(auth_password(authctxt, password));
+
+ /* now that the password has been checked, change password
+ * if requested by client and revalidate new password */
+ if (change) {
+ if (PRIVSEP(auth_change_password(authctxt, password,
+ npassword))) {
+ debug("%s: password changed successfully",
+ __func__);
+ authenticated = 1;
+ } else {
+ debug("%s: password change failed", __func__);
+ }
+ memset(npassword, 0, nlen);
+ xfree(npassword);
+ }
+ }
memset(password, 0, len);
xfree(password);
return authenticated;
diff -ru ../openssh-3.5p1.orig/auth2.c openssh-3.5p1-passexpire_pty/auth2.c
--- ../openssh-3.5p1.orig/auth2.c Thu Sep 26 10:38:49 2002
+++ openssh-3.5p1-passexpire_pty/auth2.c Tue Oct 29 23:10:37 2002
@@ -40,6 +40,7 @@
extern ServerOptions options;
extern u_char *session_id2;
extern int session_id2_len;
+extern char *password_expire_message;
Authctxt *x_authctxt = NULL;
@@ -199,6 +200,7 @@
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
{
char *methods;
+ static const char default_prompt[] = "You must change your password now.";
if (!authctxt->valid && authenticated)
fatal("INTERNAL ERROR: authenticated invalid user %s",
@@ -238,6 +240,15 @@
packet_write_wait();
/* now we can break out */
authctxt->success = 1;
+ } else if (authenticated == 2 ) { /* password change required */
+ if (password_expire_message == NULL)
+ password_expire_message = (char *)default_prompt;
+ debug("sending SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ");
+ packet_start(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ);
+ packet_put_cstring(password_expire_message);
+ packet_put_cstring(""); /* language */
+ packet_send();
+ packet_write_wait();
} else {
if (authctxt->failures++ > AUTH_FAIL_MAX) {
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
diff -ru ../openssh-3.5p1.orig/monitor.c openssh-3.5p1-passexpire_pty/monitor.c
--- ../openssh-3.5p1.orig/monitor.c Fri Sep 27 13:26:02 2002
+++ openssh-3.5p1-passexpire_pty/monitor.c Tue Oct 29 23:10:40 2002
@@ -101,6 +101,7 @@
int mm_answer_auth2_read_banner(int, Buffer *);
int mm_answer_authserv(int, Buffer *);
int mm_answer_authpassword(int, Buffer *);
+int mm_answer_auth_change_password(int, Buffer *);
int mm_answer_bsdauthquery(int, Buffer *);
int mm_answer_bsdauthrespond(int, Buffer *);
int mm_answer_skeyquery(int, Buffer *);
@@ -161,6 +162,7 @@
{MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
{MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+ {MONITOR_REQ_CHPASS, MON_AUTH, mm_answer_auth_change_password},
#ifdef USE_PAM
{MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
#endif
@@ -267,6 +269,7 @@
/* Permit requests for moduli and signatures */
monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_CHPASS, 1);
} else {
mon_dispatch = mon_dispatch_proto15;
@@ -275,8 +278,13 @@
authctxt = authctxt_new();
- /* The first few requests do not require asynchronous access */
- while (!authenticated) {
+ /*
+ * The first few requests do not require asynchronous access
+ * exit loop if authenticated and password change no required (proto 2)
+ * or if password correct (proto 1)
+ */
+ while ((compat20 && authenticated != 1) ||
+ (!compat20 && !authenticated)) {
authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
if (authenticated) {
if (!(ent->flags & MON_AUTHDECIDE))
@@ -600,13 +608,14 @@
{
static int call_count;
char *passwd;
- int authenticated;
+ int authenticated = 0;
u_int plen;
passwd = buffer_get_string(m, &plen);
/* Only authenticate if the context is valid */
- authenticated = options.password_authentication &&
- authctxt->valid && auth_password(authctxt, passwd);
+ if ( options.password_authentication && authctxt->valid )
+ authenticated = auth_password(authctxt, passwd);
+
memset(passwd, 0, strlen(passwd));
xfree(passwd);
@@ -624,6 +633,32 @@
/* Causes monitor loop to terminate if authenticated */
return (authenticated);
+}
+
+int
+mm_answer_auth_change_password(int socket, Buffer *m)
+{
+ char *oldpass, *newpass;
+ int changed;
+
+ oldpass = buffer_get_string(m, NULL);
+ newpass = buffer_get_string(m, NULL);
+
+ /* Only attempt if the context is valid */
+ if ( options.password_authentication && authctxt->valid )
+ changed = auth_change_password(authctxt, oldpass, newpass);
+
+ buffer_clear(m);
+ buffer_put_int(m, changed);
+
+ mm_request_send(socket, MONITOR_ANS_CHPASS, m);
+
+ memset(oldpass, 0, strlen(oldpass));
+ xfree(oldpass);
+ memset(newpass, 0, strlen(newpass));
+ xfree(newpass);
+
+ return changed;
}
#ifdef BSD_AUTH
diff -ru ../openssh-3.5p1.orig/monitor.h openssh-3.5p1-passexpire_pty/monitor.h
--- ../openssh-3.5p1.orig/monitor.h Fri Sep 27 13:26:02 2002
+++ openssh-3.5p1-passexpire_pty/monitor.h Tue Oct 29 23:10:41 2002
@@ -35,6 +35,7 @@
MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
+ MONITOR_REQ_CHPASS, MONITOR_ANS_CHPASS,
MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
diff -ru ../openssh-3.5p1.orig/monitor_wrap.c openssh-3.5p1-passexpire_pty/monitor_wrap.c
--- ../openssh-3.5p1.orig/monitor_wrap.c Fri Sep 27 13:26:03 2002
+++ openssh-3.5p1-passexpire_pty/monitor_wrap.c Tue Oct 29 23:10:41 2002
@@ -256,7 +256,7 @@
buffer_put_cstring(&m, password);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
- debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
+ debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD (type %d)", __func__, MONITOR_ANS_AUTHPASSWORD);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
authenticated = buffer_get_int(&m);
@@ -266,6 +266,32 @@
debug3("%s: user %sauthenticated",
__func__, authenticated ? "" : "not ");
return (authenticated);
+}
+
+int
+mm_auth_change_password(Authctxt *authctxt, char *oldpass, char *newpass)
+{
+ Buffer m;
+ int changed = 0;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, oldpass);
+ buffer_put_cstring(&m, newpass);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_CHPASS, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_CHPASS (type %d)", __func__, MONITOR_ANS_CHPASS);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_CHPASS, &m);
+
+ changed = buffer_get_int(&m);
+
+ debug3("%s: password %schanged",
+ __func__, changed ? "" : "not ");
+
+ buffer_free(&m);
+ return changed;
}
int
diff -ru ../openssh-3.5p1.orig/monitor_wrap.h openssh-3.5p1-passexpire_pty/monitor_wrap.h
--- ../openssh-3.5p1.orig/monitor_wrap.h Fri Sep 27 13:26:04 2002
+++ openssh-3.5p1-passexpire_pty/monitor_wrap.h Tue Oct 29 23:10:41 2002
@@ -46,6 +46,7 @@
struct passwd *mm_getpwnamallow(const char *);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct Authctxt *, char *);
+int mm_auth_change_password(struct Authctxt *, char *, char *);
int mm_key_allowed(enum mm_keytype, char *, char *, Key *);
int mm_user_key_allowed(struct passwd *, Key *);
int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
diff -ru ../openssh-3.5p1.orig/openbsd-compat/port-aix.c openssh-3.5p1-passexpire_pty/openbsd-compat/port-aix.c
--- ../openssh-3.5p1.orig/openbsd-compat/port-aix.c Sun Jul 7 12:17:36 2002
+++ openssh-3.5p1-passexpire_pty/openbsd-compat/port-aix.c Wed Oct 30 01:46:52 2002
@@ -24,11 +24,15 @@
*
*/
#include "includes.h"
+#include "misc.h"
+#include "log.h"
#ifdef _AIX
#include <uinfo.h>
#include <../xmalloc.h>
+#include <userpw.h>
+#include <usersec.h>
/*
* AIX has a "usrinfo" area where logname and other stuff is stored -
@@ -52,5 +56,26 @@
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 */
diff -ru ../openssh-3.5p1.orig/openbsd-compat/port-aix.h openssh-3.5p1-passexpire_pty/openbsd-compat/port-aix.h
--- ../openssh-3.5p1.orig/openbsd-compat/port-aix.h Sun Jul 7 12:17:36 2002
+++ openssh-3.5p1-passexpire_pty/openbsd-compat/port-aix.h Wed Oct 30 01:46:35 2002
@@ -25,5 +25,11 @@
*/
#ifdef _AIX
+
void aix_usrinfo(struct passwd *pw);
+
+#ifdef WITH_AIXAUTHENTICATE
+void aix_remove_embedded_newlines(char *);
+#endif
+
#endif /* _AIX */
diff -ru ../openssh-3.5p1.orig/session.c openssh-3.5p1-passexpire_pty/session.c
--- ../openssh-3.5p1.orig/session.c Thu Sep 26 10:38:50 2002
+++ openssh-3.5p1-passexpire_pty/session.c Tue Oct 29 23:10:42 2002
@@ -103,8 +103,12 @@
#define MAX_SESSIONS 10
Session sessions[MAX_SESSIONS];
+void do_tty_change_password(struct passwd *);
+extern int password_change_required;
+extern char *password_expire_message;
+
#ifdef WITH_AIXAUTHENTICATE
-char *aixloginmsg;
+char *aixloginmsg; /* message returned by loginsuccess() */
#endif /* WITH_AIXAUTHENTICATE */
#ifdef HAVE_LOGIN_CAP
@@ -461,6 +465,12 @@
"TTY available");
#endif /* USE_PAM */
+#ifdef WITH_AIXAUTHENTICATE
+ if (!compat20 && 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 +767,11 @@
}
#endif
+ if (!compat20 && password_change_required) {
+ printf("%s\n", password_expire_message);
+ do_tty_change_password(pw);
+ }
+
if (check_quietlogin(s, command))
return;
@@ -764,9 +779,18 @@
if (!is_pam_password_change_required())
print_pam_messages();
#endif /* USE_PAM */
+
+ if (password_expire_message && *password_expire_message) {
+ if (!password_change_required)
+ printf("%s\n", password_expire_message);
+ xfree(password_expire_message);
+ }
+
#ifdef WITH_AIXAUTHENTICATE
- if (aixloginmsg && *aixloginmsg)
+ if (aixloginmsg && *aixloginmsg) {
printf("%s\n", aixloginmsg);
+ xfree(aixloginmsg);
+ }
#endif /* WITH_AIXAUTHENTICATE */
#ifndef NO_SSH_LASTLOG
More information about the openssh-unix-dev
mailing list