mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-02-16 22:06:55 +00:00
- 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.
This commit is contained in:
parent
819d4526ca
commit
23bc8d0bff
@ -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 $
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
1
auth.h
@ -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' */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
89
session.c
89
session.c
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user