[auth-passwd.c auth.h pathnames.h session.c]
     support for password change; ok dtucker@
     (set password-dead=1w in login.conf to use this).
     In -Portable, this is currently only platforms using bsdauth.
This commit is contained in:
Darren Tucker 2004-02-06 16:24:31 +11:00
parent 819d4526ca
commit 23bc8d0bff
7 changed files with 147 additions and 66 deletions

View File

@ -12,6 +12,12 @@
- (dtucker) [openbsd-compat/port-aix.c openbsd-compat/port-aix.h] Bug #796:
Restore previous authdb setting after auth calls. Fixes problems with
setpcred failing on accounts that use AFS or NIS password registries.
- (dtucker) OpenBSD CVS Sync
- markus@cvs.openbsd.org 2004/01/30 09:48:57
[auth-passwd.c auth.h pathnames.h session.c]
support for password change; ok dtucker@
(set password-dead=1w in login.conf to use this).
In -Portable, this is currently only platforms using bsdauth.
20040129
- (dtucker) OpenBSD CVS Sync regress/
@ -1797,4 +1803,4 @@
- Fix sshd BindAddress and -b options for systems using fake-getaddrinfo.
Report from murple@murple.net, diagnosis from dtucker@zip.com.au
$Id: ChangeLog,v 1.3211 2004/02/06 05:18:47 dtucker Exp $
$Id: ChangeLog,v 1.3212 2004/02/06 05:24:31 dtucker Exp $

View File

@ -1,4 +1,4 @@
/* $Id: acconfig.h,v 1.172 2004/01/23 11:03:10 dtucker Exp $ */
/* $Id: acconfig.h,v 1.173 2004/02/06 05:24:31 dtucker Exp $ */
/*
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
@ -65,6 +65,9 @@
/* from environment and PATH */
#undef LOGIN_PROGRAM_FALLBACK
/* Full path of your "passwd" program */
#undef _PATH_PASSWD_PROG
/* Define if your password has a pw_class field */
#undef HAVE_PW_CLASS_IN_PASSWD

View File

@ -42,11 +42,21 @@ RCSID("$OpenBSD: auth-passwd.c,v 1.30 2003/11/04 08:54:09 djm Exp $");
#include "log.h"
#include "servconf.h"
#include "auth.h"
#include "auth-options.h"
#ifdef WITH_AIXAUTHENTICATE
# include "canohost.h"
#endif
extern ServerOptions options;
int sys_auth_passwd(Authctxt *, const char *);
static void
disable_forwarding(void)
{
no_port_forwarding_flag = 1;
no_agent_forwarding_flag = 1;
no_x11_forwarding_flag = 1;
}
/*
* Tries to authenticate the user using password. Returns true if
@ -66,17 +76,21 @@ auth_password(Authctxt *authctxt, const char *password)
return 0;
#if defined(HAVE_OSF_SIA)
/*
* XXX: any reason this is before krb? could be moved to
* sys_auth_passwd()? -dt
*/
return auth_sia_password(authctxt, password) && ok;
#else
# ifdef KRB5
#endif
#ifdef KRB5
if (options.kerberos_authentication == 1) {
int ret = auth_krb5_password(authctxt, password);
if (ret == 1 || ret == 0)
return ret && ok;
/* Fall back to ordinary passwd authentication. */
}
# endif
# ifdef HAVE_CYGWIN
#endif
#ifdef HAVE_CYGWIN
if (is_winnt) {
HANDLE hToken = cygwin_logon_user(pw, password);
@ -85,41 +99,57 @@ auth_password(Authctxt *authctxt, const char *password)
cygwin_set_impersonation_token(hToken);
return ok;
}
# endif
# ifdef WITH_AIXAUTHENTICATE
if (aix_authenticate(pw->pw_name, password,
get_canonical_hostname(options.use_dns)) == 0)
return 0;
else
return ok;
# endif
# ifdef BSD_AUTH
if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh",
(char *)password) == 0)
return 0;
else
return ok;
# else
{
#endif
return (sys_auth_passwd(authctxt, password) && ok);
}
#ifdef BSD_AUTH
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
{
struct passwd *pw = authctxt->pw;
auth_session_t *as;
as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh",
(char *)password);
if (auth_getstate(as) & AUTH_PWEXPIRED) {
auth_close(as);
disable_forwarding();
authctxt->force_pwchange = 1;
return (1);
} else {
return (auth_close(as));
}
}
#elif defined(WITH_AIXAUTHENTICATE)
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
{
return (aix_authenticate(authctxt->pw->pw_name, password,
get_canonical_hostname(options.use_dns)));
}
#else
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
{
struct passwd *pw = authctxt->pw;
char *encrypted_password;
/* Just use the supplied fake password if authctxt is invalid */
char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
/* Check for users with no password. */
if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
return ok;
else {
/* Encrypt the candidate password using the proper salt. */
char *encrypted_password = xcrypt(password,
(pw_password[0] && pw_password[1]) ? pw_password : "xx");
return (1);
/*
* Authentication is accepted if the encrypted passwords
* are identical.
*/
return (strcmp(encrypted_password, pw_password) == 0) && ok;
}
/* Encrypt the candidate password using the proper salt. */
encrypted_password = xcrypt(password,
(pw_password[0] && pw_password[1]) ? pw_password : "xx");
}
# endif
#endif /* !HAVE_OSF_SIA */
/*
* Authentication is accepted if the encrypted passwords
* are identical.
*/
return (strcmp(encrypted_password, pw_password) == 0);
}
#endif

1
auth.h
View File

@ -52,6 +52,7 @@ struct Authctxt {
int valid; /* user exists and is allowed to login */
int attempt;
int failures;
int force_pwchange;
char *user; /* username sent by the client */
char *service;
struct passwd *pw; /* set if 'valid' */

View File

@ -1,4 +1,4 @@
# $Id: configure.ac,v 1.192 2004/02/06 04:59:06 dtucker Exp $
# $Id: configure.ac,v 1.193 2004/02/06 05:24:31 dtucker Exp $
AC_INIT
AC_CONFIG_SRCDIR([ssh.c])
@ -42,6 +42,11 @@ else
fi
fi
AC_PATH_PROG(PATH_PASSWD_PROG, passwd)
if test ! -z "$PATH_PASSWD_PROG" ; then
AC_DEFINE_UNQUOTED(_PATH_PASSWD_PROG, "$PATH_PASSWD_PROG")
fi
if test -z "$LD" ; then
LD=$CC
fi

View File

@ -150,6 +150,11 @@
#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty"
#endif
/* for passwd change */
#ifndef _PATH_PASSWD_PROG
#define _PATH_PASSWD_PROG "/usr/bin/passwd"
#endif
#ifndef _PATH_LS
#define _PATH_LS "ls"
#endif

View File

@ -33,7 +33,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: session.c,v 1.171 2004/01/13 19:23:15 markus Exp $");
RCSID("$OpenBSD: session.c,v 1.172 2004/01/30 09:48:57 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
@ -1303,6 +1303,22 @@ do_setusercontext(struct passwd *pw)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
}
static void
do_pwchange(Session *s)
{
fprintf(stderr, "WARNING: Your password has expired.\n");
if (s->ttyfd != -1) {
fprintf(stderr,
"You must change your password now and login again!\n");
execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL);
perror("passwd");
} else {
fprintf(stderr,
"Password change required but no TTY available.\n");
}
exit(1);
}
static void
launch_login(struct passwd *pw, const char *hostname)
{
@ -1324,6 +1340,40 @@ launch_login(struct passwd *pw, const char *hostname)
exit(1);
}
static void
child_close_fds(void)
{
int i;
if (packet_get_connection_in() == packet_get_connection_out())
close(packet_get_connection_in());
else {
close(packet_get_connection_in());
close(packet_get_connection_out());
}
/*
* Close all descriptors related to channels. They will still remain
* open in the parent.
*/
/* XXX better use close-on-exec? -markus */
channel_close_all();
/*
* Close any extra file descriptors. Note that there may still be
* descriptors left by system functions. They will be closed later.
*/
endpwent();
/*
* Close any extra open file descriptors so that we don\'t have them
* hanging around in clients. Note that we want to do this after
* initgroups, because at least on Solaris 2.3 it leaves file
* descriptors open.
*/
for (i = 3; i < 64; i++)
close(i);
}
/*
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
@ -1337,11 +1387,18 @@ do_child(Session *s, const char *command)
char *argv[10];
const char *shell, *shell0, *hostname = NULL;
struct passwd *pw = s->pw;
u_int i;
/* remove hostkey from the child's memory */
destroy_sensitive_data();
/* Force a password change */
if (s->authctxt->force_pwchange) {
do_setusercontext(pw);
child_close_fds();
do_pwchange(s);
exit(1);
}
/* login(1) is only called if we execute the login shell */
if (options.use_login && command != NULL)
options.use_login = 0;
@ -1392,33 +1449,7 @@ do_child(Session *s, const char *command)
* closed before building the environment, as we call
* get_remote_ipaddr there.
*/
if (packet_get_connection_in() == packet_get_connection_out())
close(packet_get_connection_in());
else {
close(packet_get_connection_in());
close(packet_get_connection_out());
}
/*
* Close all descriptors related to channels. They will still remain
* open in the parent.
*/
/* XXX better use close-on-exec? -markus */
channel_close_all();
/*
* Close any extra file descriptors. Note that there may still be
* descriptors left by system functions. They will be closed later.
*/
endpwent();
/*
* Close any extra open file descriptors so that we don\'t have them
* hanging around in clients. Note that we want to do this after
* initgroups, because at least on Solaris 2.3 it leaves file
* descriptors open.
*/
for (i = 3; i < 64; i++)
close(i);
child_close_fds();
/*
* Must take new environment into use so that .ssh/rc,