summaryrefslogtreecommitdiff
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 @@
12 - (dtucker) [openbsd-compat/port-aix.c openbsd-compat/port-aix.h] Bug #796: 12 - (dtucker) [openbsd-compat/port-aix.c openbsd-compat/port-aix.h] Bug #796:
13 Restore previous authdb setting after auth calls. Fixes problems with 13 Restore previous authdb setting after auth calls. Fixes problems with
14 setpcred failing on accounts that use AFS or NIS password registries. 14 setpcred failing on accounts that use AFS or NIS password registries.
15 - (dtucker) OpenBSD CVS Sync
16 - markus@cvs.openbsd.org 2004/01/30 09:48:57
17 [auth-passwd.c auth.h pathnames.h session.c]
18 support for password change; ok dtucker@
19 (set password-dead=1w in login.conf to use this).
20 In -Portable, this is currently only platforms using bsdauth.
15 21
1620040129 2220040129
17 - (dtucker) OpenBSD CVS Sync regress/ 23 - (dtucker) OpenBSD CVS Sync regress/
@@ -1797,4 +1803,4 @@
1797 - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. 1803 - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo.
1798 Report from murple@murple.net, diagnosis from dtucker@zip.com.au 1804 Report from murple@murple.net, diagnosis from dtucker@zip.com.au
1799 1805
1800$Id: ChangeLog,v 1.3211 2004/02/06 05:18:47 dtucker Exp $ 1806$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 @@
1/* $Id: acconfig.h,v 1.172 2004/01/23 11:03:10 dtucker Exp $ */ 1/* $Id: acconfig.h,v 1.173 2004/02/06 05:24:31 dtucker Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999-2003 Damien Miller. All rights reserved. 4 * Copyright (c) 1999-2003 Damien Miller. All rights reserved.
@@ -65,6 +65,9 @@
65/* from environment and PATH */ 65/* from environment and PATH */
66#undef LOGIN_PROGRAM_FALLBACK 66#undef LOGIN_PROGRAM_FALLBACK
67 67
68/* Full path of your "passwd" program */
69#undef _PATH_PASSWD_PROG
70
68/* Define if your password has a pw_class field */ 71/* Define if your password has a pw_class field */
69#undef HAVE_PW_CLASS_IN_PASSWD 72#undef HAVE_PW_CLASS_IN_PASSWD
70 73
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 $");
42#include "log.h" 42#include "log.h"
43#include "servconf.h" 43#include "servconf.h"
44#include "auth.h" 44#include "auth.h"
45#include "auth-options.h"
45#ifdef WITH_AIXAUTHENTICATE 46#ifdef WITH_AIXAUTHENTICATE
46# include "canohost.h" 47# include "canohost.h"
47#endif 48#endif
48 49
49extern ServerOptions options; 50extern ServerOptions options;
51int sys_auth_passwd(Authctxt *, const char *);
52
53static void
54disable_forwarding(void)
55{
56 no_port_forwarding_flag = 1;
57 no_agent_forwarding_flag = 1;
58 no_x11_forwarding_flag = 1;
59}
50 60
51/* 61/*
52 * Tries to authenticate the user using password. Returns true if 62 * Tries to authenticate the user using password. Returns true if
@@ -66,17 +76,21 @@ auth_password(Authctxt *authctxt, const char *password)
66 return 0; 76 return 0;
67 77
68#if defined(HAVE_OSF_SIA) 78#if defined(HAVE_OSF_SIA)
79 /*
80 * XXX: any reason this is before krb? could be moved to
81 * sys_auth_passwd()? -dt
82 */
69 return auth_sia_password(authctxt, password) && ok; 83 return auth_sia_password(authctxt, password) && ok;
70#else 84#endif
71# ifdef KRB5 85#ifdef KRB5
72 if (options.kerberos_authentication == 1) { 86 if (options.kerberos_authentication == 1) {
73 int ret = auth_krb5_password(authctxt, password); 87 int ret = auth_krb5_password(authctxt, password);
74 if (ret == 1 || ret == 0) 88 if (ret == 1 || ret == 0)
75 return ret && ok; 89 return ret && ok;
76 /* Fall back to ordinary passwd authentication. */ 90 /* Fall back to ordinary passwd authentication. */
77 } 91 }
78# endif 92#endif
79# ifdef HAVE_CYGWIN 93#ifdef HAVE_CYGWIN
80 if (is_winnt) { 94 if (is_winnt) {
81 HANDLE hToken = cygwin_logon_user(pw, password); 95 HANDLE hToken = cygwin_logon_user(pw, password);
82 96
@@ -85,41 +99,57 @@ auth_password(Authctxt *authctxt, const char *password)
85 cygwin_set_impersonation_token(hToken); 99 cygwin_set_impersonation_token(hToken);
86 return ok; 100 return ok;
87 } 101 }
88# endif 102#endif
89# ifdef WITH_AIXAUTHENTICATE 103 return (sys_auth_passwd(authctxt, password) && ok);
90 if (aix_authenticate(pw->pw_name, password, 104}
91 get_canonical_hostname(options.use_dns)) == 0) 105
92 return 0; 106#ifdef BSD_AUTH
93 else 107int
94 return ok; 108sys_auth_passwd(Authctxt *authctxt, const char *password)
95# endif 109{
96# ifdef BSD_AUTH 110 struct passwd *pw = authctxt->pw;
97 if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh", 111 auth_session_t *as;
98 (char *)password) == 0) 112
99 return 0; 113 as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh",
100 else 114 (char *)password);
101 return ok; 115 if (auth_getstate(as) & AUTH_PWEXPIRED) {
102# else 116 auth_close(as);
103 { 117 disable_forwarding();
118 authctxt->force_pwchange = 1;
119 return (1);
120 } else {
121 return (auth_close(as));
122 }
123}
124#elif defined(WITH_AIXAUTHENTICATE)
125int
126sys_auth_passwd(Authctxt *authctxt, const char *password)
127{
128 return (aix_authenticate(authctxt->pw->pw_name, password,
129 get_canonical_hostname(options.use_dns)));
130}
131#else
132int
133sys_auth_passwd(Authctxt *authctxt, const char *password)
134{
135 struct passwd *pw = authctxt->pw;
136 char *encrypted_password;
137
104 /* Just use the supplied fake password if authctxt is invalid */ 138 /* Just use the supplied fake password if authctxt is invalid */
105 char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; 139 char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
106 140
107 /* Check for users with no password. */ 141 /* Check for users with no password. */
108 if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) 142 if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
109 return ok; 143 return (1);
110 else {
111 /* Encrypt the candidate password using the proper salt. */
112 char *encrypted_password = xcrypt(password,
113 (pw_password[0] && pw_password[1]) ? pw_password : "xx");
114 144
115 /* 145 /* Encrypt the candidate password using the proper salt. */
116 * Authentication is accepted if the encrypted passwords 146 encrypted_password = xcrypt(password,
117 * are identical. 147 (pw_password[0] && pw_password[1]) ? pw_password : "xx");
118 */
119 return (strcmp(encrypted_password, pw_password) == 0) && ok;
120 }
121 148
122 } 149 /*
123# endif 150 * Authentication is accepted if the encrypted passwords
124#endif /* !HAVE_OSF_SIA */ 151 * are identical.
152 */
153 return (strcmp(encrypted_password, pw_password) == 0);
125} 154}
155#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 {
52 int valid; /* user exists and is allowed to login */ 52 int valid; /* user exists and is allowed to login */
53 int attempt; 53 int attempt;
54 int failures; 54 int failures;
55 int force_pwchange;
55 char *user; /* username sent by the client */ 56 char *user; /* username sent by the client */
56 char *service; 57 char *service;
57 struct passwd *pw; /* set if 'valid' */ 58 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 @@
1# $Id: configure.ac,v 1.192 2004/02/06 04:59:06 dtucker Exp $ 1# $Id: configure.ac,v 1.193 2004/02/06 05:24:31 dtucker Exp $
2 2
3AC_INIT 3AC_INIT
4AC_CONFIG_SRCDIR([ssh.c]) 4AC_CONFIG_SRCDIR([ssh.c])
@@ -42,6 +42,11 @@ else
42 fi 42 fi
43fi 43fi
44 44
45AC_PATH_PROG(PATH_PASSWD_PROG, passwd)
46if test ! -z "$PATH_PASSWD_PROG" ; then
47 AC_DEFINE_UNQUOTED(_PATH_PASSWD_PROG, "$PATH_PASSWD_PROG")
48fi
49
45if test -z "$LD" ; then 50if test -z "$LD" ; then
46 LD=$CC 51 LD=$CC
47fi 52fi
diff --git a/pathnames.h b/pathnames.h
index 89e22c77a..edeff2de3 100644
--- a/pathnames.h
+++ b/pathnames.h
@@ -150,6 +150,11 @@
150#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty" 150#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty"
151#endif 151#endif
152 152
153/* for passwd change */
154#ifndef _PATH_PASSWD_PROG
155#define _PATH_PASSWD_PROG "/usr/bin/passwd"
156#endif
157
153#ifndef _PATH_LS 158#ifndef _PATH_LS
154#define _PATH_LS "ls" 159#define _PATH_LS "ls"
155#endif 160#endif
diff --git a/session.c b/session.c
index 02c5dca9b..5742296d5 100644
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
33 */ 33 */
34 34
35#include "includes.h" 35#include "includes.h"
36RCSID("$OpenBSD: session.c,v 1.171 2004/01/13 19:23:15 markus Exp $"); 36RCSID("$OpenBSD: session.c,v 1.172 2004/01/30 09:48:57 markus Exp $");
37 37
38#include "ssh.h" 38#include "ssh.h"
39#include "ssh1.h" 39#include "ssh1.h"
@@ -1304,6 +1304,22 @@ do_setusercontext(struct passwd *pw)
1304} 1304}
1305 1305
1306static void 1306static void
1307do_pwchange(Session *s)
1308{
1309 fprintf(stderr, "WARNING: Your password has expired.\n");
1310 if (s->ttyfd != -1) {
1311 fprintf(stderr,
1312 "You must change your password now and login again!\n");
1313 execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL);
1314 perror("passwd");
1315 } else {
1316 fprintf(stderr,
1317 "Password change required but no TTY available.\n");
1318 }
1319 exit(1);
1320}
1321
1322static void
1307launch_login(struct passwd *pw, const char *hostname) 1323launch_login(struct passwd *pw, const char *hostname)
1308{ 1324{
1309 /* Launch login(1). */ 1325 /* Launch login(1). */
@@ -1324,6 +1340,40 @@ launch_login(struct passwd *pw, const char *hostname)
1324 exit(1); 1340 exit(1);
1325} 1341}
1326 1342
1343static void
1344child_close_fds(void)
1345{
1346 int i;
1347
1348 if (packet_get_connection_in() == packet_get_connection_out())
1349 close(packet_get_connection_in());
1350 else {
1351 close(packet_get_connection_in());
1352 close(packet_get_connection_out());
1353 }
1354 /*
1355 * Close all descriptors related to channels. They will still remain
1356 * open in the parent.
1357 */
1358 /* XXX better use close-on-exec? -markus */
1359 channel_close_all();
1360
1361 /*
1362 * Close any extra file descriptors. Note that there may still be
1363 * descriptors left by system functions. They will be closed later.
1364 */
1365 endpwent();
1366
1367 /*
1368 * Close any extra open file descriptors so that we don\'t have them
1369 * hanging around in clients. Note that we want to do this after
1370 * initgroups, because at least on Solaris 2.3 it leaves file
1371 * descriptors open.
1372 */
1373 for (i = 3; i < 64; i++)
1374 close(i);
1375}
1376
1327/* 1377/*
1328 * Performs common processing for the child, such as setting up the 1378 * Performs common processing for the child, such as setting up the
1329 * environment, closing extra file descriptors, setting the user and group 1379 * environment, closing extra file descriptors, setting the user and group
@@ -1337,11 +1387,18 @@ do_child(Session *s, const char *command)
1337 char *argv[10]; 1387 char *argv[10];
1338 const char *shell, *shell0, *hostname = NULL; 1388 const char *shell, *shell0, *hostname = NULL;
1339 struct passwd *pw = s->pw; 1389 struct passwd *pw = s->pw;
1340 u_int i;
1341 1390
1342 /* remove hostkey from the child's memory */ 1391 /* remove hostkey from the child's memory */
1343 destroy_sensitive_data(); 1392 destroy_sensitive_data();
1344 1393
1394 /* Force a password change */
1395 if (s->authctxt->force_pwchange) {
1396 do_setusercontext(pw);
1397 child_close_fds();
1398 do_pwchange(s);
1399 exit(1);
1400 }
1401
1345 /* login(1) is only called if we execute the login shell */ 1402 /* login(1) is only called if we execute the login shell */
1346 if (options.use_login && command != NULL) 1403 if (options.use_login && command != NULL)
1347 options.use_login = 0; 1404 options.use_login = 0;
@@ -1392,33 +1449,7 @@ do_child(Session *s, const char *command)
1392 * closed before building the environment, as we call 1449 * closed before building the environment, as we call
1393 * get_remote_ipaddr there. 1450 * get_remote_ipaddr there.
1394 */ 1451 */
1395 if (packet_get_connection_in() == packet_get_connection_out()) 1452 child_close_fds();
1396 close(packet_get_connection_in());
1397 else {
1398 close(packet_get_connection_in());
1399 close(packet_get_connection_out());
1400 }
1401 /*
1402 * Close all descriptors related to channels. They will still remain
1403 * open in the parent.
1404 */
1405 /* XXX better use close-on-exec? -markus */
1406 channel_close_all();
1407
1408 /*
1409 * Close any extra file descriptors. Note that there may still be
1410 * descriptors left by system functions. They will be closed later.
1411 */
1412 endpwent();
1413
1414 /*
1415 * Close any extra open file descriptors so that we don\'t have them
1416 * hanging around in clients. Note that we want to do this after
1417 * initgroups, because at least on Solaris 2.3 it leaves file
1418 * descriptors open.
1419 */
1420 for (i = 3; i < 64; i++)
1421 close(i);
1422 1453
1423 /* 1454 /*
1424 * Must take new environment into use so that .ssh/rc, 1455 * Must take new environment into use so that .ssh/rc,