]> andersk Git - openssh.git/commitdiff
- markus@cvs.openbsd.org 2004/01/30 09:48:57
authordtucker <dtucker>
Fri, 6 Feb 2004 05:24:31 +0000 (05:24 +0000)
committerdtucker <dtucker>
Fri, 6 Feb 2004 05:24:31 +0000 (05:24 +0000)
     [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.

ChangeLog
acconfig.h
auth-passwd.c
auth.h
configure.ac
pathnames.h
session.c

index d3ddfb7c6ef120d997e481b0f801a9acf694ba27..367fce4527cbd7ab36153d2a56df53bb71c12cbe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
  - (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/
index 4c95950ca62a1e74497c779bc5c510f8ebee6271..a4ae258c26760077fe382a6fa61ad99af6049555 100644 (file)
@@ -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
 
index a27170cccb4bf76653af750782e25f698286b452..d12996bba46d49f0a8907794dd0a5ce61ad5e756 100644 (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
diff --git a/auth.h b/auth.h
index 0be1f88c4c7e1b17132896a5ffb64f9c154bb5cc..de2f1e800a69e3009fa05147cb1b16747ca5bcec 100644 (file)
--- 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' */
index 3ff673409defe6997317eaef73f80e22007992d2..7590219f081d16970a1a7d7680204ae873328b22 100644 (file)
@@ -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
index 89e22c77abe1074241d690538d25998308c902a4..edeff2de367bde958b7ca513a08a887ecaf07c07 100644 (file)
 #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
index 02c5dca9b985348f241d091648258321971a3968..5742296d5173e665e0e2e2d395c31be47685ff5f 100644 (file)
--- 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"
@@ -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,
This page took 0.756293 seconds and 5 git commands to generate.