diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2004-01-30 09:48:58 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2004-01-30 09:48:58 +0000 |
commit | 6b8cd81185d109e8cb3c1c4ee5aad053e8cf8838 (patch) | |
tree | 77a3cad5aa3d754c78031ced9f98d53deeaf8a05 /usr.bin | |
parent | 37c661a56e70ec46912339948f738f902333cee0 (diff) |
support for password change; ok dtucker@
(set password-dead=1w in login.conf to use this).
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/ssh/auth-passwd.c | 70 | ||||
-rw-r--r-- | usr.bin/ssh/auth.h | 3 | ||||
-rw-r--r-- | usr.bin/ssh/pathnames.h | 5 | ||||
-rw-r--r-- | usr.bin/ssh/session.c | 89 |
4 files changed, 116 insertions, 51 deletions
diff --git a/usr.bin/ssh/auth-passwd.c b/usr.bin/ssh/auth-passwd.c index 1ef70dee5e6..ac2f1d5b25c 100644 --- a/usr.bin/ssh/auth-passwd.c +++ b/usr.bin/ssh/auth-passwd.c @@ -36,15 +36,24 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-passwd.c,v 1.30 2003/11/04 08:54:09 djm Exp $"); +RCSID("$OpenBSD: auth-passwd.c,v 1.31 2004/01/30 09:48:57 markus Exp $"); #include "packet.h" #include "log.h" #include "servconf.h" #include "auth.h" - +#include "auth-options.h" 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 @@ -68,26 +77,47 @@ auth_password(Authctxt *authctxt, const char *password) /* Fall back to ordinary passwd authentication. */ } #endif + return (sys_auth_passwd(authctxt, password) && ok); +} + #ifdef BSD_AUTH - if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh", - (char *)password) == 0) - return 0; - else - return ok; +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)); + } +} #else +int +sys_auth_passwd(Authctxt *authctxt, const char *password) +{ + struct passwd *pw = authctxt->pw; + char *encrypted_password; + /* Check for users with no password. */ if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0) - return ok; - else { - /* Encrypt the candidate password using the proper salt. */ - char *encrypted_password = crypt(password, - (pw->pw_passwd[0] && pw->pw_passwd[1]) ? - pw->pw_passwd : "xx"); - /* - * Authentication is accepted if the encrypted passwords - * are identical. - */ - return (strcmp(encrypted_password, pw->pw_passwd) == 0) && ok; - } -#endif + return (1); + + /* Encrypt the candidate password using the proper salt. */ + encrypted_password = crypt(password, + (pw->pw_passwd[0] && pw->pw_passwd[1]) ? + pw->pw_passwd : "xx"); + + /* + * Authentication is accepted if the encrypted passwords + * are identical. + */ + return (strcmp(encrypted_password, pw->pw_passwd) == 0); } +#endif diff --git a/usr.bin/ssh/auth.h b/usr.bin/ssh/auth.h index 360e9c3c5d7..e45137bdce8 100644 --- a/usr.bin/ssh/auth.h +++ b/usr.bin/ssh/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.48 2003/11/04 08:54:09 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.49 2004/01/30 09:48:57 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -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/usr.bin/ssh/pathnames.h b/usr.bin/ssh/pathnames.h index 3bc6b50e12b..2037054a76d 100644 --- a/usr.bin/ssh/pathnames.h +++ b/usr.bin/ssh/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.13 2002/05/23 19:24:30 markus Exp $ */ +/* $OpenBSD: pathnames.h,v 1.14 2004/01/30 09:48:57 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -128,3 +128,6 @@ /* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */ #define _PATH_PRIVSEP_CHROOT_DIR "/var/empty" + +/* for passwd change */ +#define _PATH_PASSWD_PROG "/usr/bin/passwd" diff --git a/usr.bin/ssh/session.c b/usr.bin/ssh/session.c index fd3cc58a5b4..ab425aed95f 100644 --- a/usr.bin/ssh/session.c +++ b/usr.bin/ssh/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" @@ -1007,6 +1007,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). */ @@ -1020,6 +1036,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 @@ -1033,11 +1083,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; @@ -1078,33 +1135,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, |