Thayne Harbaugh <[EMAIL PROTECTED]> writes:
> /etc/shadow contains userids (which correlate to /etc/passwd),
> encrytped passwords, and password dates/days for how often
> passwords have to and can be changed, when users are warned
> about their passwords needing changing, and when accounts
> are forcibly expired. "man chage" and "man shadow".
I have tried to get this right, based on the manpages for "shadow" and
"getspnam" on a Solaris box. Some questions I could not find answers
for in the docs:
o What values will I find in the shadowpwd struct if there is no
expiration date and no limit on password age? My guess is zero.
o What about timezones? Are the absolute "days" values in sp_lstchg
and sp_expire in GMT or localtime? For now, I'm assuming GMT and if
that's wrong I hope a few hours off isn't too bad.
I would be grateful if you could review the new code (do_lookup_user()
in unix_user.c) and tell me if I have gotten the shadow stuff right.
The function is included below, the rest of the code is at
http://www.lysator.liu.se/~nisse/lsh/src as usual.
/* This method filters out accounts that are known to be disabled
* (i.e. root, or shadow style expiration). However, it may still
* return some disabled accounts.
*
* An account that is disabled in /etc/passwd should have a value for
* the login shell that prevents login; replacing the passwd field
* only doesn't prevent login using publickey authentication. */
static struct user *
do_lookup_user(struct user_db *s,
struct lsh_string *name, int free)
{
CAST(unix_user_db, self, s);
struct passwd *passwd;
name = make_cstring(name, free);
if (!name)
return NULL;
if ((passwd = getpwnam(name->data))
/* Check for root login */
&& (passwd->pw_uid || self->allow_root))
{
char *crypted;
#if HAVE_GETSPNAM
/* FIXME: What's the most portable way to test for shadow passwords?
* A single character in the passwd field should cover most variants. */
if (passwd->pw_passwd && (strlen(passwd->pw_passwd) == 1))
{
struct spwd *shadowpwd;
/* Current day number since January 1, 1970.
*
* FIXME: Which timezone is used in the /etc/shadow file? */
long now = time(NULL) / (3600 * 24);
if (!(shadowpwd = getspnam(name->data)))
goto fail;
/* FIXME: I'm assuming that zero means there's no expiry
* date. */
if (shadowpwd->sp_expire && (now > shadowpwd->sp_expire))
{
werror("Access denied for user '%pS', account expired.\n", name);
goto fail;
}
/* FIXME: I'm assuming that zero means that there is no
* restriction on password age. */
if (shadowpwd->sp_max &&
(now > (shadowpwd->sp_lstchg + shadowpwd->sp_max)))
{
werror("Access denied for user '%pS', password too old.\n", name);
goto fail;
}
/* FIXME: We could look at sp_warn and figure out if it is
* appropriate to send an SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
* message. */
crypted = shadowpwd->sp_pwdp;
}
else
#endif /* HAVE_GETSPNAM */
crypted = passwd->pw_passwd;
return make_unix_user(name,
passwd->pw_uid, passwd->pw_gid,
crypted,
passwd->pw_dir, passwd->pw_shell);
}
else
{
fail:
lsh_string_free(name);
return NULL;
}
}
Regards,
/Niels