Patch for changing expired passwords
Dave Dykstra
dwd at bell-labs.com
Tue Jun 19 23:23:10 EST 2001
On Tue, Jun 19, 2001 at 02:30:46PM +0200, Markus Friedl wrote:
> On Mon, Jun 18, 2001 at 03:55:45PM -0500, Dave Dykstra wrote:
> > The primary purpose of the attached patches is for portable OpenSSH to
> > support changing expired passwords as specified in shadow password files.
>
> hi, can you provide a
> diff -u
> version for me, too :)
>
> thanks.
Sure, sorry about that. I saw somewhere that I should provide unified
diffs but I didn't really know what that meant; now I do. The diffs
against the two CVS versions are attached.
- Dave Dykstra
-------------- next part --------------
--- auth.c.O Mon Jun 18 09:31:58 2001
+++ auth.c Mon Jun 18 09:35:08 2001
@@ -68,16 +68,25 @@
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)
+ 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))))
+ }
+ 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]))
+ 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,19 +94,27 @@
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)
+ 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)
+ 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)
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,6 +125,8 @@
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,6 +93,7 @@
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,17 +271,7 @@
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);
+ do_exec(s, command);
session_close(s);
return;
@@ -504,6 +495,35 @@
}
}
+/*
+ * 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,13 +1308,8 @@
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);
+ do_exec(s, NULL);
return 1;
}
@@ -1304,17 +1319,7 @@
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);
+ 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,6 +47,9 @@
#include "buffer.h"
#include "bufaux.h"
+/* set when password has expired */
+int forced_passwd_change = 0;
+
/* import */
extern ServerOptions options;
@@ -81,13 +84,23 @@
int days = time(NULL) / 86400;
/* Check account expiry */
- if ((spw->sp_expire >= 0) && (days > spw->sp_expire))
+ 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)))
- return 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,7 +190,7 @@
}
/* Remove trailing newline */
*--p = '\0';
- log("Login restricted for %s: %.100s", pw->pw_name, loginmsg);
+ 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,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.O2 Mon Jun 18 14:21:15 2001
+++ session.c Mon Jun 18 14:39:36 2001
@@ -603,6 +603,34 @@
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,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