View | Details | Raw Unified | Return to bug 14 | Differences between
and this patch

Collapse All | Expand All

(-)TODO (-2 lines)
Lines 15-22 Link Here
15
15
16
- More platforms for for setproctitle() emulation (testing needed)
16
- More platforms for for setproctitle() emulation (testing needed)
17
17
18
- Handle changing passwords for the non-PAM expired password case
19
20
- Improve PAM support (a pam_lastlog module will cause sshd to exit)
18
- Improve PAM support (a pam_lastlog module will cause sshd to exit)
21
  and maybe support alternate forms of authentications like OPIE via
19
  and maybe support alternate forms of authentications like OPIE via
22
  pam?
20
  pam?
(-)acconfig.h (+3 lines)
Lines 25-30 Link Here
25
/* from environment and PATH */
25
/* from environment and PATH */
26
#undef LOGIN_PROGRAM_FALLBACK
26
#undef LOGIN_PROGRAM_FALLBACK
27
27
28
/* Path to passwd program */
29
#undef PASSWD_PROGRAM_PATH
30
28
/* Define if your password has a pw_class field */
31
/* Define if your password has a pw_class field */
29
#undef HAVE_PW_CLASS_IN_PASSWD
32
#undef HAVE_PW_CLASS_IN_PASSWD
30
33
(-)auth-pam.c (-20 / +4 lines)
Lines 42-49 Link Here
42
42
43
#define NEW_AUTHTOK_MSG \
43
#define NEW_AUTHTOK_MSG \
44
	"Warning: Your password has expired, please change it now."
44
	"Warning: Your password has expired, please change it now."
45
#define NEW_AUTHTOK_MSG_PRIVSEP \
46
	"Your password has expired, the session cannot proceed."
47
45
48
static int do_pam_conversation(int num_msg, const struct pam_message **msg,
46
static int do_pam_conversation(int num_msg, const struct pam_message **msg,
49
	struct pam_response **resp, void *appdata_ptr);
47
	struct pam_response **resp, void *appdata_ptr);
Lines 60-66 Link Here
60
/* states for do_pam_conversation() */
58
/* states for do_pam_conversation() */
61
enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN;
59
enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN;
62
/* remember whether pam_acct_mgmt() returned PAM_NEW_AUTHTOK_REQD */
60
/* remember whether pam_acct_mgmt() returned PAM_NEW_AUTHTOK_REQD */
63
static int password_change_required = 0;
61
extern int password_change_required;
64
/* remember whether the last pam_authenticate() succeeded or not */
62
/* remember whether the last pam_authenticate() succeeded or not */
65
static int was_authenticated = 0;
63
static int was_authenticated = 0;
66
64
Lines 248-265 Link Here
248
		case PAM_SUCCESS:
246
		case PAM_SUCCESS:
249
			/* This is what we want */
247
			/* This is what we want */
250
			break;
248
			break;
251
#if 0
252
		case PAM_NEW_AUTHTOK_REQD:
249
		case PAM_NEW_AUTHTOK_REQD:
253
			message_cat(&__pam_msg, use_privsep ?
250
			message_cat(&__pam_msg, NEW_AUTHTOK_MSG);
254
			    NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG);
251
			flag_password_change_required();
255
			/* flag that password change is necessary */
256
			password_change_required = 1;
257
			/* disallow other functionality for now */
258
			no_port_forwarding_flag |= 2;
259
			no_agent_forwarding_flag |= 2;
260
			no_x11_forwarding_flag |= 2;
261
			break;
252
			break;
262
#endif
263
		default:
253
		default:
264
			logit("PAM rejected by account configuration[%d]: "
254
			logit("PAM rejected by account configuration[%d]: "
265
			    "%.200s", pam_retval, PAM_STRERROR(__pamh, 
255
			    "%.200s", pam_retval, PAM_STRERROR(__pamh, 
Lines 345-357 Link Here
345
			fatal("PAM pam_chauthtok failed[%d]: %.200s",
335
			fatal("PAM pam_chauthtok failed[%d]: %.200s",
346
			    pam_retval, PAM_STRERROR(__pamh, pam_retval));
336
			    pam_retval, PAM_STRERROR(__pamh, pam_retval));
347
#if 0
337
#if 0
348
		/* XXX: This would need to be done in the parent process,
338
		flag_password_change_successful();
349
		 * but there's currently no way to pass such request. */
350
		no_port_forwarding_flag &= ~2;
351
		no_agent_forwarding_flag &= ~2;
352
		no_x11_forwarding_flag &= ~2;
353
		if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
354
			channel_permit_all_opens();
355
#endif
339
#endif
356
	}
340
	}
357
}
341
}
(-)auth-passwd.c (-11 / +90 lines)
Lines 42-47 Link Here
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 "buffer.h"
46
#include "misc.h"
47
#include "channels.h"
48
#include "auth-options.h"
45
49
46
#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
50
#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
47
/* Don't need any of these headers for the PAM or SIA cases */
51
/* Don't need any of these headers for the PAM or SIA cases */
Lines 81-89 Link Here
81
#endif /* !USE_PAM && !HAVE_OSF_SIA */
85
#endif /* !USE_PAM && !HAVE_OSF_SIA */
82
86
83
extern ServerOptions options;
87
extern ServerOptions options;
84
#ifdef WITH_AIXAUTHENTICATE
88
85
extern char *aixloginmsg;
89
int password_change_required = 0;
86
#endif
87
90
88
/*
91
/*
89
 * Tries to authenticate the user using password.  Returns true if
92
 * Tries to authenticate the user using password.  Returns true if
Lines 153-167 Link Here
153
# endif
156
# endif
154
# ifdef WITH_AIXAUTHENTICATE
157
# ifdef WITH_AIXAUTHENTICATE
155
	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
158
	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
156
159
	aix_remove_embedded_newlines(authmsg);
157
	if (authsuccess)
160
	if (authsuccess)
158
	        /* We don't have a pty yet, so just label the line as "ssh" */
161
		debug3("AIX/authenticate succeeded for user %s: %.100s",
159
	        if (loginsuccess(authctxt->user,
162
		    pw->pw_name, authmsg);
160
			get_canonical_hostname(options.verify_reverse_mapping),
163
	else
161
			"ssh", &aixloginmsg) < 0)
164
		debug3("AIX/authenticate failed for user %s: %.100s",
162
				aixloginmsg = NULL;
165
		    pw->pw_name, authmsg);
163
166
	if (authmsg)
164
	return(authsuccess);
167
		xfree(authmsg);
168
	return authsuccess;
165
# endif
169
# endif
166
# ifdef KRB4
170
# ifdef KRB4
167
	if (options.kerberos_authentication == 1) {
171
	if (options.kerberos_authentication == 1) {
Lines 236-239 Link Here
236
	/* Authentication is accepted if the encrypted passwords are identical. */
240
	/* Authentication is accepted if the encrypted passwords are identical. */
237
	return (strcmp(encrypted_password, pw_password) == 0);
241
	return (strcmp(encrypted_password, pw_password) == 0);
238
#endif /* !USE_PAM && !HAVE_OSF_SIA */
242
#endif /* !USE_PAM && !HAVE_OSF_SIA */
243
}
244
245
/*
246
 * Perform generic password change via tty. Like do_pam_chauthtok(),
247
 * it throws a fatal error if the password can't be changed.
248
 */
249
int
250
do_tty_change_password(struct passwd *pw)
251
{
252
	pid_t pid;
253
	int status;
254
	mysig_t old_signal;
255
256
	old_signal = mysignal(SIGCHLD, SIG_DFL);
257
258
	if ((pid = fork()) == -1)
259
		fatal("Couldn't fork: %s", strerror(errno));
260
261
	if (pid == 0) {
262
		setuid(pw->pw_uid);
263
		if (geteuid() == 0) 
264
			execl(PASSWD_PROGRAM_PATH, "passwd", pw->pw_name,
265
			    (char *)NULL);
266
		else
267
			execl(PASSWD_PROGRAM_PATH, "passwd", (char *)NULL);
268
			
269
		/* execl shouldn't return */
270
		fatal("Couldn't exec %s", PASSWD_PROGRAM_PATH);
271
		exit(1);
272
	}
273
274
	if (waitpid(pid, &status, 0) == -1)
275
		fatal("Couldn't wait for child: %s", strerror(errno));
276
	mysignal(SIGCHLD, old_signal);
277
278
	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
279
		debug("%s password changed sucessfully", __func__);
280
		flag_password_change_successful();
281
		return 1;
282
	} else {
283
		fatal("Failed to change password for %s, passwd returned %d",
284
		    pw->pw_name, status);
285
		return 0;
286
	}
287
}
288
289
/*
290
 * flag that password change is necessary
291
 */
292
void
293
flag_password_change_required(void)
294
{
295
	debug3("disabling forwarding");
296
	password_change_required = 1;
297
298
	/* disallow other functionality for now */
299
	no_port_forwarding_flag |= 2;
300
	no_agent_forwarding_flag |= 2;
301
	no_x11_forwarding_flag |= 2;
302
}
303
304
/*
305
 * password change successful
306
 * XXX: must be done in parent, but currently there is no way to pass
307
 * this request.
308
 */
309
void
310
flag_password_change_successful(void)
311
{
312
	debug3("resetting forwarding flags");
313
314
	password_change_required = 0;
315
	no_port_forwarding_flag &= ~2;
316
	no_agent_forwarding_flag &= ~2;
317
	no_x11_forwarding_flag &= ~2;
239
}
318
}
(-)auth.c (-31 / +159 lines)
Lines 36-41 Link Here
36
#include <libgen.h>
36
#include <libgen.h>
37
#endif
37
#endif
38
38
39
#ifdef WITH_AIXAUTHENTICATE
40
#include <userpw.h>
41
#include <usersec.h>
42
#endif
43
39
#include "xmalloc.h"
44
#include "xmalloc.h"
40
#include "match.h"
45
#include "match.h"
41
#include "groupaccess.h"
46
#include "groupaccess.h"
Lines 51-59 Link Here
51
#include "misc.h"
56
#include "misc.h"
52
#include "bufaux.h"
57
#include "bufaux.h"
53
#include "packet.h"
58
#include "packet.h"
59
#include "sshlogin.h"
54
60
55
/* import */
61
/* import */
56
extern ServerOptions options;
62
extern ServerOptions options;
63
extern Buffer expire_message;
64
extern Buffer login_message;
57
65
58
/* Debugging messages */
66
/* Debugging messages */
59
Buffer auth_debug;
67
Buffer auth_debug;
Lines 75-83 Link Here
75
	const char *hostname = NULL, *ipaddr = NULL;
83
	const char *hostname = NULL, *ipaddr = NULL;
76
	char *shell;
84
	char *shell;
77
	int i;
85
	int i;
78
#ifdef WITH_AIXAUTHENTICATE
79
	char *loginmsg;
80
#endif /* WITH_AIXAUTHENTICATE */
81
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
86
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
82
    !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
87
    !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
83
	struct spwd *spw;
88
	struct spwd *spw;
Lines 88-122 Link Here
88
	if (!pw || !pw->pw_name)
93
	if (!pw || !pw->pw_name)
89
		return 0;
94
		return 0;
90
95
96
#define	DAY		(24L * 60 * 60) /* 1 day in seconds */
97
#define WEEK		(DAY * 7)	/* 1 week in seconds */
91
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
98
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
92
    !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
99
    !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
93
#define	DAY		(24L * 60 * 60) /* 1 day in seconds */
94
	if ((spw = getspnam(pw->pw_name)) != NULL) {
100
	if ((spw = getspnam(pw->pw_name)) != NULL) {
101
		int daysleft;
102
95
		today = time(NULL) / DAY;
103
		today = time(NULL) / DAY;
96
		debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
104
		debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
97
		    " sp_max %d", (int)today, (int)spw->sp_expire,
105
		    " sp_max %d sp_warn %d", (int)today, (int)spw->sp_expire,
98
		    (int)spw->sp_lstchg, (int)spw->sp_max);
106
		    (int)spw->sp_lstchg, (int)spw->sp_max, (int)spw->sp_warn);
99
107
100
		/*
108
		/*
101
		 * We assume account and password expiration occurs the
109
		 * We assume account and password expiration occurs the
102
		 * day after the day specified.
110
		 * day after the day specified.
103
		 */
111
		 */
104
		if (spw->sp_expire != -1 && today > spw->sp_expire) {
112
		daysleft = spw->sp_expire - today;
113
		if (spw->sp_expire == -1) {
114
			debug3("account expiration disabled");
115
		} else if (today > spw->sp_expire) {
105
			logit("Account %.100s has expired", pw->pw_name);
116
			logit("Account %.100s has expired", pw->pw_name);
106
			return 0;
117
			return 0;
107
		}
118
		} else if (daysleft <= spw->sp_warn) {
119
			char buf[256];
108
120
121
			debug3("account will expire in %d days", daysleft);
122
			snprintf(buf, sizeof(buf),
123
			    "Your account will expire in %d day%s.\n",
124
			    daysleft, daysleft == 1 ? "" : "s");
125
			buffer_append(&login_message, buf, strlen(buf));
126
		}
127
		
128
#define PWCHG_FORCED    "You must change your password now.\n"
129
#define PWCHG_EXPIRED   "Your password has expired, you must change it now.\n"
130
		daysleft = spw->sp_lstchg + spw->sp_max - today;
109
		if (spw->sp_lstchg == 0) {
131
		if (spw->sp_lstchg == 0) {
110
			logit("User %.100s password has expired (root forced)",
132
			logit("User %.100s password has expired (root forced)",
111
			    pw->pw_name);
133
			    pw->pw_name);
112
			return 0;
134
			flag_password_change_required();
113
		}
135
			buffer_append(&expire_message, PWCHG_FORCED,
114
136
			    sizeof(PWCHG_FORCED));
115
		if (spw->sp_max != -1 &&
137
		} else if (spw->sp_max == -1) {
116
		    today > spw->sp_lstchg + spw->sp_max) {
138
			debug3("password expiration disabled");
139
		} else if (daysleft < 0) {
117
			logit("User %.100s password has expired (password aged)",
140
			logit("User %.100s password has expired (password aged)",
118
			    pw->pw_name);
141
			    pw->pw_name);
119
			return 0;
142
			flag_password_change_required();
143
			buffer_append(&expire_message, PWCHG_EXPIRED,
144
			    sizeof(PWCHG_EXPIRED));
145
		} else if (daysleft <= spw->sp_warn) {
146
			char buf[256];
147
148
			debug3("password will expire in %d days", daysleft);
149
			snprintf(buf, sizeof(buf),
150
			    "Your password will expire in %d day%s.\n",
151
			    daysleft, daysleft == 1 ? "" : "s");
152
			buffer_append(&expire_message, buf, strlen(buf));
120
		}
153
		}
121
	}
154
	}
122
#endif
155
#endif
Lines 206-231 Link Here
206
	 * PermitRootLogin to control logins via ssh), or if running as
239
	 * PermitRootLogin to control logins via ssh), or if running as
207
	 * non-root user (since loginrestrictions will always fail).
240
	 * non-root user (since loginrestrictions will always fail).
208
	 */
241
	 */
209
	if ((pw->pw_uid != 0) && (geteuid() == 0) &&
242
	if ( (pw->pw_uid != 0) && (geteuid() == 0) ) {
210
	    loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
211
		int loginrestrict_errno = errno;
243
		int loginrestrict_errno = errno;
244
		char *msg;
212
245
213
		if (loginmsg && *loginmsg) {
246
		/* check for AIX account restrictions */
214
			/* Remove embedded newlines (if any) */
247
		if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg) != 0) {
215
			char *p;
248
			if (msg && *msg) {
216
			for (p = loginmsg; *p; p++) {
249
				aix_remove_embedded_newlines(msg);
217
				if (*p == '\n')
250
				log("Login restricted for %s: %.100s",
218
					*p = ' ';
251
				    pw->pw_name, msg);
252
				xfree(msg);
219
			}
253
			}
220
			/* Remove trailing newline */
254
221
			*--p = '\0';
255
			/* Don't fail if /etc/nologin  set */
222
			logit("Login restricted for %s: %.100s", pw->pw_name, 
256
			if (!(loginrestrict_errno == EPERM &&
223
			    loginmsg);
257
			    stat(_PATH_NOLOGIN, &st) == 0))
224
		}
258
				return 0;
225
		/* Don't fail if /etc/nologin  set */
259
		}
226
	    	if (!(loginrestrict_errno == EPERM && 
260
	}
227
		    stat(_PATH_NOLOGIN, &st) == 0))
261
228
			return 0;
262
263
	/*
264
	 * Check AIX password expiry.  Only check when running as root.
265
	 * Unpriv'ed users can't access /etc/security/passwd or
266
	 * /etc/security/user so passwdexpired will always fail.
267
	 */
268
	if (geteuid() == 0) {
269
		char *msg, *user = pw->pw_name;
270
		int result, maxage, result2, maxexpired;
271
		struct userpw *upw;
272
273
		/* Check if password expired too long as in this case,
274
		 * passwdexpired still returns 1 but /bin/passwd will fail */
275
		upw = getuserpw(user);
276
		result = getuserattr(user, S_MAXEXPIRED, &maxexpired, SEC_INT);
277
		result2 = getuserattr(user, S_MAXAGE, &maxage, SEC_INT);
278
		if (upw != NULL && result == 0 && result2 == 0) {
279
			time_t now = time(NULL);
280
281
			debug3("%s lastupdate %lu maxage %d wks maxexpired %d"
282
			    "wks time now %d", __func__, upw->upw_lastupdate,
283
			    maxage, maxexpired, now);
284
285
			if (maxexpired != -1 && maxage != 0 &&
286
		       	    upw->upw_lastupdate + ((maxage+maxexpired) * WEEK) <= now ){
287
				log("User %.100s password expired too long",
288
				    user);
289
				return 0;
290
			}
291
		}
292
293
		result = passwdexpired(user, &msg);
294
		if (msg && *msg) {
295
			aix_remove_embedded_newlines(msg);
296
			buffer_append(&expire_message, msg, strlen(msg));
297
		}
298
		debug3("AIX/passwdexpired returned %d msg %.100s", result, msg);
299
300
		switch (result) {
301
			case 0: /* success, password not expired */
302
				break;
303
			case 1: /* expired, password change required */
304
				flag_password_change_required();
305
				break;
306
			default: /* user can't change(2) or other error (-1) */
307
				logit("Password can't be changed for user %s: "
308
				    "%.100s", user, msg);
309
				if (msg)
310
					xfree(msg);
311
				return 0;
312
		}
313
		if (msg)
314
			xfree(msg);
229
	}
315
	}
230
#endif /* WITH_AIXAUTHENTICATE */
316
#endif /* WITH_AIXAUTHENTICATE */
231
317
Lines 241-246 Link Here
241
	return authctxt;
327
	return authctxt;
242
}
328
}
243
329
330
/*
331
 * Generate last_login message and store for later display.  This must be
332
 * called before login_login() is called and lastlog is updated.
333
 */
334
void
335
generate_login_message(const char *user, uid_t uid, const char *host)
336
{
337
#ifdef WITH_AIXAUTHENTICATE
338
	char *msg;
339
340
	/* We don't have a pty yet, so just label the line as "ssh" */
341
	if (loginsuccess(user, host, "ssh", &msg) >= 0)
342
		buffer_append(&login_message, msg, strlen(msg));
343
#elif !defined(NO_SSH_LASTLOG)
344
	if (options.print_lastlog) {
345
		char *time_string, lasthost[MAXHOSTNAMELEN], buf[256];
346
		time_t last_login_time;
347
348
		last_login_time = get_last_login_time(uid, user, lasthost,
349
		   sizeof(lasthost));
350
351
		if (last_login_time != 0) {
352
		       time_string = ctime(&last_login_time);
353
		       if (strchr(time_string, '\n'))
354
			       *strchr(time_string, '\n') = 0;
355
		       if (strcmp(lasthost, "") == 0)
356
			       snprintf(buf, sizeof(buf),
357
				   "Last login: %s\r\n",
358
				   time_string);
359
		       else
360
			       snprintf(buf, sizeof(buf),
361
				   "Last login: %s from %s\r\n",
362
				   time_string, lasthost);
363
		       buffer_append(&login_message, buf, strlen(buf));
364
		}
365
       }
366
#endif
367
}
368
244
void
369
void
245
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
370
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
246
{
371
{
Lines 268-273 Link Here
268
	    get_remote_port(),
393
	    get_remote_port(),
269
	    info);
394
	    info);
270
395
396
	if (authenticated && geteuid() == 0)
397
		generate_login_message(authctxt->user, authctxt->pw->pw_uid,
398
		    get_canonical_hostname(options.verify_reverse_mapping));
271
#ifdef WITH_AIXAUTHENTICATE
399
#ifdef WITH_AIXAUTHENTICATE
272
	if (authenticated == 0 && strcmp(method, "password") == 0)
400
	if (authenticated == 0 && strcmp(method, "password") == 0)
273
	    loginfailed(authctxt->user,
401
	    loginfailed(authctxt->user,
(-)auth.h (+3 lines)
Lines 156-161 Link Here
156
156
157
int	allowed_user(struct passwd *);
157
int	allowed_user(struct passwd *);
158
struct passwd * getpwnamallow(const char *user);
158
struct passwd * getpwnamallow(const char *user);
159
int	do_tty_change_password(struct passwd *pw);
160
void	flag_password_change_required(void);
161
void	flag_password_change_successful(void);
159
162
160
char	*get_challenge(Authctxt *);
163
char	*get_challenge(Authctxt *);
161
int	verify_response(Authctxt *, const char *);
164
int	verify_response(Authctxt *, const char *);
(-)configure.ac (+7 lines)
Lines 41-46 Link Here
41
	fi
41
	fi
42
fi
42
fi
43
43
44
AC_PATH_PROG(PASSWD_PROGRAM_PATH, passwd)
45
if test ! -z "$PASSWD_PROGRAM_PATH" ; then
46
	AC_DEFINE_UNQUOTED(PASSWD_PROGRAM_PATH, "$PASSWD_PROGRAM_PATH")
47
else
48
	AC_MSG_ERROR([*** passwd command not found - check config.log ***])
49
fi
50
44
if test -z "$LD" ; then
51
if test -z "$LD" ; then
45
	LD=$CC
52
	LD=$CC
46
fi
53
fi
(-)session.c (-34 / +26 lines)
Lines 95-100 Link Here
95
extern u_int utmp_len;
95
extern u_int utmp_len;
96
extern int startup_pipe;
96
extern int startup_pipe;
97
extern void destroy_sensitive_data(void);
97
extern void destroy_sensitive_data(void);
98
extern Buffer expire_message;
99
extern Buffer login_message;
100
extern int password_change_required;
98
101
99
/* original command from peer. */
102
/* original command from peer. */
100
const char *original_command = NULL;
103
const char *original_command = NULL;
Lines 103-112 Link Here
103
#define MAX_SESSIONS 10
106
#define MAX_SESSIONS 10
104
Session	sessions[MAX_SESSIONS];
107
Session	sessions[MAX_SESSIONS];
105
108
106
#ifdef WITH_AIXAUTHENTICATE
107
char *aixloginmsg;
108
#endif /* WITH_AIXAUTHENTICATE */
109
110
#ifdef HAVE_LOGIN_CAP
109
#ifdef HAVE_LOGIN_CAP
111
login_cap_t *lc;
110
login_cap_t *lc;
112
#endif
111
#endif
Lines 458-467 Link Here
458
#if defined(USE_PAM)
457
#if defined(USE_PAM)
459
	do_pam_session(s->pw->pw_name, NULL);
458
	do_pam_session(s->pw->pw_name, NULL);
460
	do_pam_setcred(1);
459
	do_pam_setcred(1);
461
	if (is_pam_password_change_required())
460
#endif /* USE_PAM */
461
462
	if (password_change_required)
462
		packet_disconnect("Password change required but no "
463
		packet_disconnect("Password change required but no "
463
		    "TTY available");
464
		    "TTY available");
464
#endif /* USE_PAM */
465
465
466
	/* Fork the child. */
466
	/* Fork the child. */
467
	if ((pid = fork()) == 0) {
467
	if ((pid = fork()) == 0) {
Lines 721-730 Link Here
721
void
721
void
722
do_login(Session *s, const char *command)
722
do_login(Session *s, const char *command)
723
{
723
{
724
	char *time_string;
725
	socklen_t fromlen;
724
	socklen_t fromlen;
726
	struct sockaddr_storage from;
725
	struct sockaddr_storage from;
727
	struct passwd * pw = s->pw;
726
	struct passwd * pw = s->pw;
727
	int password_changed = 0;
728
	pid_t pid = getpid();
728
	pid_t pid = getpid();
729
729
730
	/*
730
	/*
Lines 748-788 Link Here
748
		    options.verify_reverse_mapping),
748
		    options.verify_reverse_mapping),
749
		    (struct sockaddr *)&from, fromlen);
749
		    (struct sockaddr *)&from, fromlen);
750
750
751
#ifdef USE_PAM
752
	/*
751
	/*
753
	 * If password change is needed, do it now.
752
	 * If password change is needed, do it now.
754
	 * This needs to occur before the ~/.hushlogin check.
753
	 * This needs to occur before the ~/.hushlogin check.
755
	 */
754
	 */
756
	if (is_pam_password_change_required()) {
755
	buffer_append(&expire_message, "\0", 1);
756
	if (password_change_required) {
757
#ifdef USE_PAM
757
		print_pam_messages();
758
		print_pam_messages();
758
		do_pam_chauthtok();
759
		if (use_privsep)
759
	}
760
			do_pam_chauthtok();
761
		else
762
			do_tty_change_password(pw);
763
#else
764
		printf("%s", (char *)buffer_ptr(&expire_message));
765
		do_tty_change_password(pw);
760
#endif
766
#endif
767
		password_changed = 1;
768
	}
761
769
762
	if (check_quietlogin(s, command))
770
	if (check_quietlogin(s, command))
763
		return;
771
		return;
764
772
773
	if (!password_changed) {
765
#ifdef USE_PAM
774
#ifdef USE_PAM
766
	if (!is_pam_password_change_required())
767
		print_pam_messages();
775
		print_pam_messages();
776
#else
777
		printf("%s", (char *)buffer_ptr(&expire_message));
768
#endif /* USE_PAM */
778
#endif /* USE_PAM */
769
#ifdef WITH_AIXAUTHENTICATE
770
	if (aixloginmsg && *aixloginmsg)
771
		printf("%s\n", aixloginmsg);
772
#endif /* WITH_AIXAUTHENTICATE */
773
774
#ifndef NO_SSH_LASTLOG
775
	if (options.print_lastlog && s->last_login_time != 0) {
776
		time_string = ctime(&s->last_login_time);
777
		if (strchr(time_string, '\n'))
778
			*strchr(time_string, '\n') = 0;
779
		if (strcmp(s->hostname, "") == 0)
780
			printf("Last login: %s\r\n", time_string);
781
		else
782
			printf("Last login: %s from %s\r\n", time_string,
783
			    s->hostname);
784
	}
779
	}
785
#endif /* NO_SSH_LASTLOG */
780
781
	/* display post-login message */
782
	buffer_append(&login_message, "\0", 1);
783
	printf("%s", (char *)buffer_ptr(&login_message));
786
784
787
	do_motd();
785
	do_motd();
788
}
786
}
Lines 1603-1614 Link Here
1603
	if (s->ttyfd != -1) {
1601
	if (s->ttyfd != -1) {
1604
		packet_disconnect("Protocol error: you already have a pty.");
1602
		packet_disconnect("Protocol error: you already have a pty.");
1605
		return 0;
1603
		return 0;
1606
	}
1607
	/* Get the time and hostname when the user last logged in. */
1608
	if (options.print_lastlog) {
1609
		s->hostname[0] = '\0';
1610
		s->last_login_time = get_last_login_time(s->pw->pw_uid,
1611
		    s->pw->pw_name, s->hostname, sizeof(s->hostname));
1612
	}
1604
	}
1613
1605
1614
	s->term = packet_get_string(&len);
1606
	s->term = packet_get_string(&len);
(-)session.h (-3 lines)
Lines 39-47 Link Here
39
	int	ptyfd, ttyfd, ptymaster;
39
	int	ptyfd, ttyfd, ptymaster;
40
	u_int	row, col, xpixel, ypixel;
40
	u_int	row, col, xpixel, ypixel;
41
	char	tty[TTYSZ];
41
	char	tty[TTYSZ];
42
	/* last login */
43
	char	hostname[MAXHOSTNAMELEN];
44
	time_t	last_login_time;
45
	/* X11 */
42
	/* X11 */
46
	u_int	display_number;
43
	u_int	display_number;
47
	char	*display;
44
	char	*display;
(-)sshd.c (+7 lines)
Lines 205-210 Link Here
205
int use_privsep;
205
int use_privsep;
206
struct monitor *pmonitor;
206
struct monitor *pmonitor;
207
207
208
Buffer expire_message; /* "password will expire/has expired" messages */
209
Buffer login_message;  /* message to be displayed after login */
210
208
/* Prototypes for various functions defined later in this file. */
211
/* Prototypes for various functions defined later in this file. */
209
void destroy_sensitive_data(void);
212
void destroy_sensitive_data(void);
210
void demote_sensitive_data(void);
213
void demote_sensitive_data(void);
Lines 1505-1510 Link Here
1505
	if (use_privsep)
1508
	if (use_privsep)
1506
		if ((authctxt = privsep_preauth()) != NULL)
1509
		if ((authctxt = privsep_preauth()) != NULL)
1507
			goto authenticated;
1510
			goto authenticated;
1511
1512
	/* prepare buffers to collect authentication/expiry messages */
1513
	buffer_init(&login_message);
1514
	buffer_init(&expire_message);
1508
1515
1509
	/* perform the key exchange */
1516
	/* perform the key exchange */
1510
	/* authenticate user and start session */
1517
	/* authenticate user and start session */
(-)version.h (-1 / +1 lines)
Lines 1-3 Link Here
1
/* $OpenBSD: version.h,v 1.37 2003/04/01 10:56:46 markus Exp $ */
1
/* $OpenBSD: version.h,v 1.37 2003/04/01 10:56:46 markus Exp $ */
2
2
3
#define SSH_VERSION    "OpenSSH_3.6.1p2"
3
#define SSH_VERSION    "OpenSSH_3.6.1p2-pwexp19"
(-)openbsd-compat/port-aix.c (-1 / +21 lines)
Lines 52-56 Link Here
52
	xfree(cp);
52
	xfree(cp);
53
}
53
}
54
54
55
#endif /* _AIX */
55
#ifdef WITH_AIXAUTHENTICATE
56
/*
57
 * Remove embedded newlines in string (if any).
58
 * Used before logging messages returned by AIX authentication functions
59
 * so the message is logged on one line.
60
 */
61
void
62
aix_remove_embedded_newlines(char *p)
63
{
64
	if (p == NULL)
65
		return;
66
67
	for (; *p; p++) {
68
		if (*p == '\n')
69
			*p = ' ';
70
	}
71
	/* Remove trailing newline */
72
	*--p = '\0';
73
}
74
#endif /* WITH_AIXAUTHENTICATE */
56
75
76
#endif /* _AIX */
(-)openbsd-compat/port-aix.h (+1 lines)
Lines 37-40 Link Here
37
#endif
37
#endif
38
38
39
void aix_usrinfo(struct passwd *pw);
39
void aix_usrinfo(struct passwd *pw);
40
void aix_remove_embedded_newlines(char *);
40
#endif /* _AIX */
41
#endif /* _AIX */

Return to bug 14