[PATCH] AIX password expiration
Darren Tucker
dtucker at zip.com.au
Sun Oct 13 21:37:18 EST 2002
Hi All.
With one eye on the do_pam_chauthtok() stuff I've merged contributions
by Pablo Sor and Mark Pitt into a patch against -current. I'm
interested in testers and suggestions for improvements.
The patch extends the loginrestrictions test to include expired
accounts (but unlike Mark's patch, doesn't log accounts with expired
passwords unless they're locked) and adds PAM-like password expiry and
forced change (based on Pablo's patch).
Tested on AIX 4.3.3 with and without privsep, including regression
tests.
-Daz.
Threads:
http://marc.theaimsgroup.com/?l=openssh-unix-dev&m=99962930031063
http://marc.theaimsgroup.com/?l=openssh-unix-dev&m=100497021226430
Examples:
$ ssh -l testuser locahost
testuser at localhost's password:
Your password will expire: Sun Oct 20 20:14:49 2002
[snip]
$ ssh -l testuser localhost
testuser at dlocalhost's password:
You are required to change your password. Please choose a new one.
Changing password for "testuser"
testuser's Old password:
testuser's New password:
Enter the new password again:
[snip]
--
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 --------------
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 */
More information about the openssh-unix-dev
mailing list