Patch for changing expired passwords

Dave Dykstra dwd at bell-labs.com
Tue Oct 16 04:00:54 EST 2001


On Fri, Oct 12, 2001 at 02:42:28PM -0700, Iain Morgan wrote:
> A fix for this issue is definitely needed. We have had to back off of
> implementing OpenSSH on our SGI's and Crays due to the issue of password
> expiration.
> 
> At a glance, one item that I would take execption with is the special handling
> for root. Perhaps the behaviour for root should be configurable.

I certainly wouldn't want an extra configuration option, but looking back I
can't think of any reason why I would have put that check in there.  I took
it out; the updated patch is below.  I tested expiring a root login, and
there's not even any adverse interactions with the PermitRootLogin option,
because that is checked separately before it gets to allowed_user() in
auth.c.

- Dave Dykstra


--- auth.c.O	Fri Oct 12 14:42:38 2001
+++ auth.c	Mon Oct 15 13:57:05 2001
@@ -49,6 +49,9 @@
 #include "uidswap.h"
 #include "tildexpand.h"
 
+/* set when password has expired */
+int forced_passwd_change = 0;
+
 /* import */
 extern ServerOptions options;
 
@@ -90,7 +93,7 @@
 		/* Check password expiry */
 		if ((spw->sp_lstchg >= 0) && (spw->sp_max >= 0) &&
 		    (days > (spw->sp_lstchg + spw->sp_max)))
-			return 0;
+			forced_passwd_change = 1;
 	}
 #else
 	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
--- auth.h.O	Thu Aug 23 13:18:52 2001
+++ auth.h	Fri Oct 12 15:00:10 2001
@@ -40,6 +40,9 @@
 #include <krb5.h>
 #endif
 
+/* set when password has expired */
+extern int forced_passwd_change;
+
 typedef struct Authctxt Authctxt;
 typedef struct KbdintDevice KbdintDevice;
 
--- session.c.O	Fri Oct 12 14:42:41 2001
+++ session.c	Fri Oct 12 15:04:29 2001
@@ -656,7 +656,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;
 		debug("Forced command '%.900s'", command);
--- configure.in.O	Fri Oct 12 14:42:39 2001
+++ configure.in	Fri Oct 12 15:00:57 2001
@@ -1449,6 +1449,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	Fri Oct 12 14:42:37 2001
+++ acconfig.h	Mon Oct 15 13:59:02 2001
@@ -214,6 +214,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