Patch for changing expired passwords

Dave Dykstra dwd at bell-labs.com
Fri Jun 22 04:08:07 EST 2001


Markus has now installed a variation on my changes to session.c into
openbsd openssh CVS, and Ben has pulled in the session.c changes into the
portable openssh CVS, so here is an update of my patch based on the current
portable openssh CVS.  Markus decided to defer the additional logging I
suggested in auth.c, so I left that out.

Note: I pointed out to Markus in private email that the line 
"forced_command = NULL" should not be there in do_exec(), and it is
unfortunately in the context of the following diff so if that change
gets applied first this might not apply cleanly anymore.

- Dave Dykstra


--- auth.c.O	Mon Jun 18 14:19:54 2001
+++ auth.c	Thu Jun 21 11:22:34 2001
@@ -47,6 +47,9 @@
 #include "buffer.h"
 #include "bufaux.h"
 
+/* set when password has expired */
+int forced_passwd_change = 0;
+
 /* import */
 extern ServerOptions options;
 
@@ -86,8 +89,12 @@
 
 		/* Check password expiry */
 		if ((spw->sp_lstchg >= 0) && (spw->sp_max >= 0) &&
-		    (days > (spw->sp_lstchg + spw->sp_max)))
-			return 0;
+		    (days > (spw->sp_lstchg + spw->sp_max))) {
+			if ((pw->pw_uid == 0))
+				return 0;
+
+			forced_passwd_change = 1;
+		}
 	}
 #else
 	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
--- auth.h.O	Tue Jun  5 15:25:06 2001
+++ auth.h	Mon Jun 18 14:28:04 2001
@@ -35,6 +35,9 @@
 #include <bsd_auth.h>
 #endif
 
+/* set when password has expired */
+extern int forced_passwd_change;
+
 typedef struct Authctxt Authctxt;
 typedef struct KbdintDevice KbdintDevice;
 
--- session.c.O	Thu Jun 21 11:09:30 2001
+++ session.c	Thu Jun 21 11:16:42 2001
@@ -596,7 +596,31 @@
 void
 do_exec(Session *s, const char *command)
 {
-	if (forced_command) {
+	if (forced_passwd_change) {
+		char *user = s->pw->pw_name;
+		char *msg;
+
+		if (s->ttyfd != -1) {
+			msg = "Password for %.100s has expired, running 'passwd' to reset it";
+			/*
+			 * Can't pass "user" to 'passwd' because Linux doesn't
+			 * allow it.
+			 * Also, the prompt is friendlier without "user".
+			 */
+			command = PASSWD_PATH;
+		} else {
+			msg = "Password for %.100s has expired and cannot be changed without a pty";
+			/*
+			 * Without a pty, Solaris 'passwd' prints "Permission
+			 * denied", but Linux attempts to change the password
+			 * and fails miserably, so echo an error message instead
+			 */
+			command = "/bin/sh -c 'echo Permission denied >&2; exit 1'";
+		}
+		log(msg, user);
+		packet_send_debug(msg, user);
+
+	} else if (forced_command) {
 		original_command = command;
 		command = forced_command;
 		forced_command = NULL;
--- configure.in.O	Sun Jun 10 12:24:52 2001
+++ configure.in	Mon Jun 18 14:27:23 2001
@@ -1304,6 +1304,10 @@
 	AC_DEFINE_UNQUOTED(RSH_PATH, "$rsh_path")
 fi
 
+AC_PATH_PROG(PASSWD_PATH, passwd)
+AC_DEFINE_UNQUOTED(PASSWD_PATH, "$PASSWD_PATH")
+
+
 # Check for mail directory (last resort if we cannot get it from headers)
 if test ! -z "$MAIL" ; then
 	maildir=`dirname $MAIL`
--- acconfig.h.O	Tue May  8 15:33:06 2001
+++ acconfig.h	Mon Jun 18 14:30:16 2001
@@ -211,6 +211,9 @@
 /* Define if rsh is found in your path */
 #undef RSH_PATH
 
+/* Define if passwd is found in your path */
+#undef PASSWD_PATH
+
 /* Define if you want to allow MD5 passwords */
 #undef HAVE_MD5_PASSWORDS
 



More information about the openssh-unix-dev mailing list