Patch for changing expired passwords

Dave Dykstra dwd at bell-labs.com
Tue Jun 19 06:55:45 EST 2001


The primary purpose of the attached patches is for portable OpenSSH to
support changing expired passwords as specified in shadow password files.

To support that, I did a couple enhancements to the base OpenBSD OpenSSH
code.  They are:

    1. Consolidated the handling of "forced_command" into a do_exec()
	function in session.c.  These were being handled inconsistently and
	allocated memory was not always being properly freed.
    2. Added log messages to say why a user is disallowed by allowed_user()
	in session.c.

Those two changes are in attachment #1, against the current OpenBSD OpenSSH
CVS.  I hope Markus will accept them.

Attachment #2 contains additional changes against the portable OpenSSH CVS
to invoke the 'passwd' command whenever a shadow password entry expires and
a pseudo-tty is available.  This approach is similar to what was used by
SSH 1.2.27, but more robust because 1.2.27 would attempt to change a
password when there was no pty and fail (not to mention that it didn't work
on Linux at all because the Linux "passwd" command only permits root to
pass a username), and 1.2.27 gave no clue to the user as to why it was
asking for the password.  I decided that the 1.2.27 sshd_config option
ForcedPasswdChange was not worth putting in because I can't see why anybody
would want to turn it off and always deny expired passwords (as currently
happens in OpenSSH); if somebody wants to completely expire an account on a
specific date, there's a separate field for that in the shadow password
file.

I have tested these changes on Solaris 2.7, Linux 2.4, Irix 6.2, and
Unixware 1.1.2.  Apply attachment #1 first, then attachment #2 to the
current portable OpenSSH CVS.

Attachment #3 is a single patch file for all the changes against
OpenSSH_2.9p2 in case anybody else on the list wants to try it.

- Dave Dykstra
-------------- next part --------------
*** auth.c.O	Mon Jun 18 09:31:58 2001
--- auth.c	Mon Jun 18 09:35:08 2001
***************
*** 68,83 ****
  	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
  
  	/* deny if shell does not exists or is not executable */
! 	if (stat(shell, &st) != 0)
  		return 0;
! 	if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP))))
  		return 0;
  
  	/* Return false if user is listed in DenyUsers */
  	if (options.num_deny_users > 0) {
  		for (i = 0; i < options.num_deny_users; i++)
! 			if (match_pattern(pw->pw_name, options.deny_users[i]))
  				return 0;
  	}
  	/* Return false if AllowUsers isn't empty and user isn't listed there */
  	if (options.num_allow_users > 0) {
--- 68,92 ----
  	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
  
  	/* deny if shell does not exists or is not executable */
! 	if (stat(shell, &st) != 0) {
! 		log("User %.100s not allowed because shell %.100s does not exist",
! 			pw->pw_name, shell);
  		return 0;
! 	}
! 	if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) {
! 		log("User %.100s not allowed because shell %.100s is not executable",
! 			pw->pw_name, shell);
  		return 0;
+ 	}
  
  	/* Return false if user is listed in DenyUsers */
  	if (options.num_deny_users > 0) {
  		for (i = 0; i < options.num_deny_users; i++)
! 			if (match_pattern(pw->pw_name, options.deny_users[i])) {
! 				log("User %.100s not allowed because listed in DenyUsers",
! 					pw->pw_name);
  				return 0;
+ 			}
  	}
  	/* Return false if AllowUsers isn't empty and user isn't listed there */
  	if (options.num_allow_users > 0) {
***************
*** 85,97 ****
  			if (match_pattern(pw->pw_name, options.allow_users[i]))
  				break;
  		/* i < options.num_allow_users iff we break for loop */
! 		if (i >= options.num_allow_users)
  			return 0;
  	}
  	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
  		/* Get the user's group access list (primary and supplementary) */
! 		if (ga_init(pw->pw_name, pw->pw_gid) == 0)
  			return 0;
  
  		/* Return false if one of user's groups is listed in DenyGroups */
  		if (options.num_deny_groups > 0)
--- 94,112 ----
  			if (match_pattern(pw->pw_name, options.allow_users[i]))
  				break;
  		/* i < options.num_allow_users iff we break for loop */
! 		if (i >= options.num_allow_users) {
! 			log("User %.100s not allowed because not listed in AllowUsers",
! 				pw->pw_name);
  			return 0;
+ 		}
  	}
  	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
  		/* Get the user's group access list (primary and supplementary) */
! 		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
! 			log("User %.100s not allowed because not in any group",
! 				pw->pw_name);
  			return 0;
+ 		}
  
  		/* Return false if one of user's groups is listed in DenyGroups */
  		if (options.num_deny_groups > 0)
***************
*** 98,103 ****
--- 113,120 ----
  			if (ga_match(options.deny_groups,
  			    options.num_deny_groups)) {
  				ga_free();
+ 				log("User %.100s not allowed because a group is listed in DenyGroups",
+ 					pw->pw_name);
  				return 0;
  			}
  		/*
***************
*** 108,113 ****
--- 125,132 ----
  			if (!ga_match(options.allow_groups,
  			    options.num_allow_groups)) {
  				ga_free();
+ 				log("User %.100s not allowed because none of user's group are listed in AllowGroups",
+ 					pw->pw_name);
  				return 0;
  			}
  		ga_free();
*** session.c.O	Mon Jun 18 13:59:57 2001
--- session.c	Mon Jun 18 14:15:29 2001
***************
*** 93,98 ****
--- 93,99 ----
  void	session_close(Session *s);
  void	do_exec_pty(Session *s, const char *command);
  void	do_exec_no_pty(Session *s, const char *command);
+ void	do_exec(Session *s, const char *command);
  void	do_login(Session *s, const char *command);
  void	do_child(Session *s, const char *command);
  void	do_motd(void);
***************
*** 270,286 ****
  				command = NULL;
  				packet_integrity_check(plen, 0, type);
  			}
! 			if (forced_command != NULL) {
! 				original_command = command;
! 				command = forced_command;
! 				debug("Forced command '%.500s'", forced_command);
! 			}
! 			if (s->ttyfd != -1)
! 				do_exec_pty(s, command);
! 			else
! 				do_exec_no_pty(s, command);
! 			if (command != NULL)
! 				xfree(command);
  			session_close(s);
  			return;
  
--- 271,277 ----
  				command = NULL;
  				packet_integrity_check(plen, 0, type);
  			}
! 			do_exec(s, command);
  			session_close(s);
  			return;
  
***************
*** 504,509 ****
--- 495,529 ----
  	}
  }
  
+ /*
+  * This is called to fork and execute a command.  If another command is
+  *   to be forced, execute that instead.
+  */
+ void
+ do_exec(Session *s, const char *command)
+ {
+ 	if (forced_command) {
+ 		original_command = command;
+ 		command = forced_command;
+ 		forced_command = NULL;
+ 		debug("Forced command '%.900s'", command);
+ 	}
+ 
+ 	if (s->ttyfd != -1)
+ 		do_exec_pty(s, command);
+ 	else
+ 		do_exec_no_pty(s, command);
+ 
+ 	if (command != NULL)
+ 		xfree(command);
+ 
+ 	if (original_command != NULL) {
+ 		xfree(original_command);
+ 		original_command = NULL;
+ 	}
+ }
+ 
+ 
  /* administrative, login(1)-like work */
  void
  do_login(Session *s, const char *command)
***************
*** 1288,1300 ****
  int
  session_shell_req(Session *s)
  {
- 	/* if forced_command == NULL, the shell is execed */
- 	char *shell = forced_command;
  	packet_done();
! 	if (s->ttyfd == -1)
! 		do_exec_no_pty(s, shell);
! 	else
! 		do_exec_pty(s, shell);
  	return 1;
  }
  
--- 1308,1315 ----
  int
  session_shell_req(Session *s)
  {
  	packet_done();
! 	do_exec(s, NULL);
  	return 1;
  }
  
***************
*** 1304,1320 ****
  	u_int len;
  	char *command = packet_get_string(&len);
  	packet_done();
! 	if (forced_command) {
! 		original_command = command;
! 		command = forced_command;
! 		debug("Forced command '%.500s'", forced_command);
! 	}
! 	if (s->ttyfd == -1)
! 		do_exec_no_pty(s, command);
! 	else
! 		do_exec_pty(s, command);
! 	if (forced_command == NULL)
! 		xfree(command);
  	return 1;
  }
  
--- 1319,1325 ----
  	u_int len;
  	char *command = packet_get_string(&len);
  	packet_done();
! 	do_exec(s, command);
  	return 1;
  }
  
-------------- next part --------------
*** auth.c.O2	Mon Jun 18 14:21:06 2001
--- auth.c	Mon Jun 18 14:24:33 2001
***************
*** 47,52 ****
--- 47,55 ----
  #include "buffer.h"
  #include "bufaux.h"
  
+ /* set when password has expired */
+ int forced_passwd_change = 0;
+ 
  /* import */
  extern ServerOptions options;
  
***************
*** 81,93 ****
  		int days = time(NULL) / 86400;
  
  		/* Check account expiry */
! 		if ((spw->sp_expire >= 0) && (days > spw->sp_expire))
  			return 0;
  
  		/* Check password expiry */
  		if ((spw->sp_lstchg >= 0) && (spw->sp_max >= 0) &&
! 		    (days > (spw->sp_lstchg + spw->sp_max)))
! 			return 0;
  	}
  #else
  	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
--- 84,106 ----
  		int days = time(NULL) / 86400;
  
  		/* Check account expiry */
! 		if ((spw->sp_expire >= 0) && (days > spw->sp_expire)) {
! 			log("User %.100s not allowed because account expired",
! 				pw->pw_name);
  			return 0;
+ 		}
  
  		/* Check password expiry */
  		if ((spw->sp_lstchg >= 0) && (spw->sp_max >= 0) &&
! 		    (days > (spw->sp_lstchg + spw->sp_max))) {
! 			if ((pw->pw_uid == 0)) {
! 				log("User %.100s not allowed because password expired",
! 					pw->pw_name);
! 				return 0;
! 			}
! 
! 			forced_passwd_change = 1;
! 		}
  	}
  #else
  	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
***************
*** 177,183 ****
  			}
  			/* Remove trailing newline */
  			*--p = '\0';
! 			log("Login restricted for %s: %.100s", pw->pw_name, loginmsg);
  		}
  		return 0;
  	}
--- 190,196 ----
  			}
  			/* Remove trailing newline */
  			*--p = '\0';
! 			log("Login restricted for %.100s: %.100s", pw->pw_name, loginmsg);
  		}
  		return 0;
  	}
*** auth.h.O	Tue Jun  5 15:25:06 2001
--- auth.h	Mon Jun 18 14:28:04 2001
***************
*** 35,40 ****
--- 35,43 ----
  #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.O2	Mon Jun 18 14:21:15 2001
--- session.c	Mon Jun 18 14:39:36 2001
***************
*** 603,608 ****
--- 603,636 ----
  		debug("Forced command '%.900s'", command);
  	}
  
+ 	if (forced_passwd_change) {
+ 		char *user = s->pw->pw_name;
+ 		char *msg;
+ 
+ 		if (command != NULL)
+ 			xfree(command);
+ 
+ 		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 = xstrdup(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 = xstrdup("/bin/sh -c 'echo Permission denied >&2; exit 1'");
+ 		}
+ 		log(msg, user);
+ 		packet_send_debug(msg, user);
+ 	}
+ 
  	if (s->ttyfd != -1)
  		do_exec_pty(s, command);
  	else
*** configure.in.O	Sun Jun 10 12:24:52 2001
--- configure.in	Mon Jun 18 14:27:23 2001
***************
*** 1304,1309 ****
--- 1304,1313 ----
  	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,216 ****
--- 211,219 ----
  /* 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
  
-------------- next part --------------
*** auth.c.O	Mon Jun 18 14:50:25 2001
--- auth.c	Mon Jun 18 14:50:29 2001
***************
*** 41,46 ****
--- 41,49 ----
  #include "auth-options.h"
  #include "canohost.h"
  
+ /* set when password has expired */
+ int forced_passwd_change = 0;
+ 
  /* import */
  extern ServerOptions options;
  
***************
*** 75,87 ****
  		int days = time(NULL) / 86400;
  
  		/* Check account expiry */
! 		if ((spw->sp_expire >= 0) && (days > spw->sp_expire))
  			return 0;
  
  		/* Check password expiry */
  		if ((spw->sp_lstchg >= 0) && (spw->sp_max >= 0) &&
! 		    (days > (spw->sp_lstchg + spw->sp_max)))
! 			return 0;
  	}
  #else
  	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
--- 78,100 ----
  		int days = time(NULL) / 86400;
  
  		/* Check account expiry */
! 		if ((spw->sp_expire >= 0) && (days > spw->sp_expire)) {
! 			log("User %.100s not allowed because account expired",
! 				pw->pw_name);
  			return 0;
+ 		}
  
  		/* Check password expiry */
  		if ((spw->sp_lstchg >= 0) && (spw->sp_max >= 0) &&
! 		    (days > (spw->sp_lstchg + spw->sp_max))) {
! 			if ((pw->pw_uid == 0)) {
! 				log("User %.100s not allowed because password expired",
! 					pw->pw_name);
! 				return 0;
! 			}
! 
! 			forced_passwd_change = 1;
! 		}
  	}
  #else
  	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
***************
*** 96,111 ****
  	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
  
  	/* deny if shell does not exists or is not executable */
! 	if (stat(shell, &st) != 0)
  		return 0;
! 	if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP))))
  		return 0;
  
  	/* Return false if user is listed in DenyUsers */
  	if (options.num_deny_users > 0) {
  		for (i = 0; i < options.num_deny_users; i++)
! 			if (match_pattern(pw->pw_name, options.deny_users[i]))
  				return 0;
  	}
  	/* Return false if AllowUsers isn't empty and user isn't listed there */
  	if (options.num_allow_users > 0) {
--- 109,133 ----
  	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
  
  	/* deny if shell does not exists or is not executable */
! 	if (stat(shell, &st) != 0) {
! 		log("User %.100s not allowed because shell %.100s does not exist",
! 			pw->pw_name, shell);
  		return 0;
! 	}
! 	if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) {
! 		log("User %.100s not allowed because shell %.100s is not executable",
! 			pw->pw_name, shell);
  		return 0;
+ 	}
  
  	/* Return false if user is listed in DenyUsers */
  	if (options.num_deny_users > 0) {
  		for (i = 0; i < options.num_deny_users; i++)
! 			if (match_pattern(pw->pw_name, options.deny_users[i])) {
! 				log("User %.100s not allowed because listed in DenyUsers",
! 					pw->pw_name);
  				return 0;
+ 			}
  	}
  	/* Return false if AllowUsers isn't empty and user isn't listed there */
  	if (options.num_allow_users > 0) {
***************
*** 113,125 ****
  			if (match_pattern(pw->pw_name, options.allow_users[i]))
  				break;
  		/* i < options.num_allow_users iff we break for loop */
! 		if (i >= options.num_allow_users)
  			return 0;
  	}
  	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
  		/* Get the user's group access list (primary and supplementary) */
! 		if (ga_init(pw->pw_name, pw->pw_gid) == 0)
  			return 0;
  
  		/* Return false if one of user's groups is listed in DenyGroups */
  		if (options.num_deny_groups > 0)
--- 135,153 ----
  			if (match_pattern(pw->pw_name, options.allow_users[i]))
  				break;
  		/* i < options.num_allow_users iff we break for loop */
! 		if (i >= options.num_allow_users) {
! 			log("User %.100s not allowed because not listed in AllowUsers",
! 				pw->pw_name);
  			return 0;
+ 		}
  	}
  	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
  		/* Get the user's group access list (primary and supplementary) */
! 		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
! 			log("User %.100s not allowed because not in any group",
! 				pw->pw_name);
  			return 0;
+ 		}
  
  		/* Return false if one of user's groups is listed in DenyGroups */
  		if (options.num_deny_groups > 0)
***************
*** 126,131 ****
--- 154,161 ----
  			if (ga_match(options.deny_groups,
  			    options.num_deny_groups)) {
  				ga_free();
+ 				log("User %.100s not allowed because a group is listed in DenyGroups",
+ 					pw->pw_name);
  				return 0;
  			}
  		/*
***************
*** 136,141 ****
--- 166,173 ----
  			if (!ga_match(options.allow_groups,
  			    options.num_allow_groups)) {
  				ga_free();
+ 				log("User %.100s not allowed because none of user's group are listed in AllowGroups",
+ 					pw->pw_name);
  				return 0;
  			}
  		ga_free();
***************
*** 152,158 ****
  			}
  			/* Remove trailing newline */
  			*--p = '\0';
! 			log("Login restricted for %s: %.100s", pw->pw_name, loginmsg);
  		}
  		return 0;
  	}
--- 184,190 ----
  			}
  			/* Remove trailing newline */
  			*--p = '\0';
! 			log("Login restricted for %.100s: %.100s", pw->pw_name, loginmsg);
  		}
  		return 0;
  	}
*** auth.h.O	Mon Jun 18 14:50:25 2001
--- auth.h	Mon Jun 18 14:50:29 2001
***************
*** 35,40 ****
--- 35,43 ----
  #include <bsd_auth.h>
  #endif
  
+ /* set when password has expired */
+ extern int forced_passwd_change;
+ 
  typedef struct Authctxt Authctxt;
  struct Authctxt {
  	int success;
*** session.c.O	Mon Jun 18 14:50:25 2001
--- session.c	Mon Jun 18 14:50:29 2001
***************
*** 126,131 ****
--- 126,132 ----
  void	session_proctitle(Session *s);
  void	do_exec_pty(Session *s, const char *command);
  void	do_exec_no_pty(Session *s, const char *command);
+ void	do_exec(Session *s, const char *command);
  void	do_login(Session *s, const char *command);
  #ifdef LOGIN_NEEDS_UTMPX
  void	do_pre_login(Session *s);
***************
*** 394,411 ****
  				command = NULL;
  				packet_integrity_check(plen, 0, type);
  			}
! 			if (forced_command != NULL) {
! 				original_command = command;
! 				command = forced_command;
! 				debug("Forced command '%.500s'", forced_command);
! 			}
! 			if (have_pty)
! 				do_exec_pty(s, command);
! 			else
! 				do_exec_no_pty(s, command);
! 
! 			if (command != NULL)
! 				xfree(command);
  			return;
  
  		default:
--- 395,401 ----
  				command = NULL;
  				packet_integrity_check(plen, 0, type);
  			}
! 			do_exec(s, command);
  			return;
  
  		default:
***************
*** 680,685 ****
--- 670,732 ----
  }
  #endif
  
+ /*
+  * This is called to fork and execute a command.  If another command is
+  *   to be forced, execute that instead.
+  */
+ void
+ do_exec(Session *s, const char *command)
+ {
+ 	if (forced_command) {
+ 		original_command = command;
+ 		command = forced_command;
+ 		forced_command = NULL;
+ 		debug("Forced command '%.900s'", command);
+ 	}
+ 
+ 	if (forced_passwd_change) {
+ 		char *user = s->pw->pw_name;
+ 		char *msg;
+ 
+ 		if (command != NULL)
+ 			xfree(command);
+ 
+ 		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 = xstrdup(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 = xstrdup("/bin/sh -c 'echo Permission denied >&2; exit 1'");
+ 		}
+ 		log(msg, user);
+ 		packet_send_debug(msg, user);
+ 	}
+ 
+ 	if (s->ttyfd != -1)
+ 		do_exec_pty(s, command);
+ 	else
+ 		do_exec_no_pty(s, command);
+ 
+ 	if (command != NULL)
+ 		xfree(command);
+ 
+ 	if (original_command != NULL) {
+ 		xfree(original_command);
+ 		original_command = NULL;
+ 	}
+ }
+ 
+ 
  /* administrative, login(1)-like work */
  void
  do_login(Session *s, const char *command)
***************
*** 1737,1749 ****
  int
  session_shell_req(Session *s)
  {
- 	/* if forced_command == NULL, the shell is execed */
- 	char *shell = forced_command;
  	packet_done();
! 	if (s->ttyfd == -1)
! 		do_exec_no_pty(s, shell);
! 	else
! 		do_exec_pty(s, shell);
  	return 1;
  }
  
--- 1784,1791 ----
  int
  session_shell_req(Session *s)
  {
  	packet_done();
! 	do_exec(s, NULL);
  	return 1;
  }
  
***************
*** 1753,1769 ****
  	u_int len;
  	char *command = packet_get_string(&len);
  	packet_done();
! 	if (forced_command) {
! 		original_command = command;
! 		command = forced_command;
! 		debug("Forced command '%.500s'", forced_command);
! 	}
! 	if (s->ttyfd == -1)
! 		do_exec_no_pty(s, command);
! 	else
! 		do_exec_pty(s, command);
! 	if (forced_command == NULL)
! 		xfree(command);
  	return 1;
  }
  
--- 1795,1801 ----
  	u_int len;
  	char *command = packet_get_string(&len);
  	packet_done();
! 	do_exec(s, command);
  	return 1;
  }
  
*** configure.in.O	Mon Jun 18 14:50:25 2001
--- configure.in	Mon Jun 18 14:50:29 2001
***************
*** 1302,1307 ****
--- 1302,1311 ----
  	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	Mon Jun 18 14:50:25 2001
--- acconfig.h	Mon Jun 18 14:50:31 2001
***************
*** 211,216 ****
--- 211,219 ----
  /* 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