summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--acconfig.h5
-rw-r--r--auth-passwd.c98
-rw-r--r--auth.h1
-rw-r--r--configure.ac7
-rw-r--r--pathnames.h5
-rw-r--r--session.c89
7 files changed, 147 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index 7bc43d0db..518c51bfd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 $
diff --git a/acconfig.h b/acconfig.h
index 27366ed17..62252d760 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -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
diff --git a/auth-passwd.c b/auth-passwd.c
index a27170ccc..d12996bba 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -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
diff --git a/auth.h b/auth.h
index 0be1f88c4..de2f1e800 100644
--- a/auth.h
+++ b/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' */
diff --git a/configure.ac b/configure.ac
index 768b174b2..64645217d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/pathnames.h b/pathnames.h
index 89e22c77a..edeff2de3 100644
--- a/pathnames.h
+++ b/pathnames.h
@@ -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
diff --git a/session.c b/session.c
index 02c5dca9b..5742296d5 100644
--- a/session.c
+++ b/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"
@@ -1304,6 +1304,22 @@ do_setusercontext(struct passwd *pw)
}
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)
{
/* Launch login(1). */
@@ -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,