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
			log("PAM rejected by account configuration[%d]: "
254
			log("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 / +116 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
90
pid_t password_change_pid;	/* pid used to reset forwarding flags */
87
91
88
/*
92
/*
89
 * Tries to authenticate the user using password.  Returns true if
93
 * Tries to authenticate the user using password.  Returns true if
Lines 148-162 Link Here
148
# endif
152
# endif
149
# ifdef WITH_AIXAUTHENTICATE
153
# ifdef WITH_AIXAUTHENTICATE
150
	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
154
	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
151
155
	aix_remove_embedded_newlines(authmsg);
152
	if (authsuccess)
156
	if (authsuccess)
153
	        /* We don't have a pty yet, so just label the line as "ssh" */
157
		debug3("AIX/authenticate succeeded for user %s: %.100s",
154
	        if (loginsuccess(authctxt->user,
158
		    pw->pw_name, authmsg);
155
			get_canonical_hostname(options.verify_reverse_mapping),
159
	else
156
			"ssh", &aixloginmsg) < 0)
160
		debug3("AIX/authenticate failed for user %s: %.100s",
157
				aixloginmsg = NULL;
161
		    pw->pw_name, authmsg);
158
162
	if (authmsg)
159
	return(authsuccess);
163
		xfree(authmsg);
164
	return authsuccess;
160
# endif
165
# endif
161
# ifdef KRB4
166
# ifdef KRB4
162
	if (options.kerberos_authentication == 1) {
167
	if (options.kerberos_authentication == 1) {
Lines 231-234 Link Here
231
	/* Authentication is accepted if the encrypted passwords are identical. */
236
	/* Authentication is accepted if the encrypted passwords are identical. */
232
	return (strcmp(encrypted_password, pw_password) == 0);
237
	return (strcmp(encrypted_password, pw_password) == 0);
233
#endif /* !USE_PAM && !HAVE_OSF_SIA */
238
#endif /* !USE_PAM && !HAVE_OSF_SIA */
239
}
240
241
/*
242
 * Perform generic password change via tty. Like do_pam_chauthtok(),
243
 * it throws a fatal error if the password can't be changed.
244
 */
245
int
246
do_tty_change_password(struct passwd *pw)
247
{
248
	pid_t pid;
249
	int status;
250
	mysig_t old_signal;
251
252
	old_signal = mysignal(SIGCHLD, SIG_DFL);
253
254
	if ((pid = fork()) == -1)
255
		fatal("Couldn't fork: %s", strerror(errno));
256
257
	if (pid == 0) {
258
		setuid(pw->pw_uid);
259
		if (geteuid() == 0) 
260
			execl(PASSWD_PROGRAM_PATH, "passwd", pw->pw_name,
261
			    (char *)NULL);
262
		else
263
			execl(PASSWD_PROGRAM_PATH, "passwd", (char *)NULL);
264
			
265
		/* execl shouldn't return */
266
		fatal("Couldn't exec %s", PASSWD_PROGRAM_PATH);
267
		exit(1);
268
	}
269
270
	if (waitpid(pid, &status, 0) == -1)
271
		fatal("Couldn't wait for child: %s", strerror(errno));
272
	mysignal(SIGCHLD, old_signal);
273
274
	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
275
		debug("%s password changed sucessfully", __func__);
276
		flag_password_change_successful();
277
		return 1;
278
	} else {
279
		fatal("Failed to change password for %s, passwd returned %d",
280
		    pw->pw_name, status);
281
		return 0;
282
	}
283
}
284
285
/*
286
 * Because an expired password is changed after forking to exec the user's
287
 * shell, restoring the port forwarding flags is done by sending a
288
 * USR1 signal to the parent after the password is changed successfully.
289
 */
290
void
291
flag_password_change_required(void)
292
{
293
	debug("%s disabling forwarding flags", __func__);
294
	/* flag that password change is necessary */
295
	password_change_required = 1;
296
297
	/* disallow other functionality for now */
298
	no_port_forwarding_flag |= 2;
299
	no_agent_forwarding_flag |= 2;
300
	no_x11_forwarding_flag |= 2;
301
302
	/* set handler to reset flags */
303
	password_change_pid = getpid();
304
	mysignal(SIGUSR1, password_change_successful_handler);
305
}
306
307
/*
308
 * password change successful, tell parent to restore port
309
 * forwarding flags
310
 */
311
void
312
flag_password_change_successful(void)
313
{
314
	debug("%s signalling parent to reset forwarding flags", __func__);
315
	kill(password_change_pid, SIGUSR1);
316
317
	/* reset flags in local process too */
318
	password_change_required = 0;
319
	no_port_forwarding_flag &= ~2;
320
	no_agent_forwarding_flag &= ~2;
321
	no_x11_forwarding_flag &= ~2;
322
}
323
324
/*
325
 * signal handler to reset change flags
326
 */
327
void
328
password_change_successful_handler(int sig)
329
{
330
	debug("%s restoring port forwarding flags", __func__);
331
	mysignal(SIGUSR1, SIG_DFL);     /* unset handler */
332
333
	password_change_required = 0;
334
	no_port_forwarding_flag &= ~2;
335
	no_agent_forwarding_flag &= ~2;
336
	no_x11_forwarding_flag &= ~2;
337
	if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
338
		channel_permit_all_opens();
234
}
339
}
(-)auth.c (-32 / +156 lines)
Lines 23-29 Link Here
23
 */
23
 */
24
24
25
#include "includes.h"
25
#include "includes.h"
26
RCSID("$OpenBSD: auth.c,v 1.46 2002/11/04 10:07:53 markus Exp $");
26
RCSID("$OpenBSD: auth.c,v 1.45 2002/09/20 18:41:29 stevesk Exp $");
27
27
28
#ifdef HAVE_LOGIN_H
28
#ifdef HAVE_LOGIN_H
29
#include <login.h>
29
#include <login.h>
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
			log("Account %.100s has expired", pw->pw_name);
116
			log("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
			log("User %.100s password has expired (root forced)",
132
			log("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
			log("User %.100s password has expired (password aged)",
140
			log("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
			log("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;
270
		int result, maxexpired;
271
		struct userpw *upw;
272
273
		/* check if password expired too long */
274
		upw = getuserpw(pw->pw_name);
275
		result = getuserattr(pw->pw_name, S_MAXEXPIRED, &maxexpired,
276
		    SEC_INT);
277
		if (upw != NULL && result == 0) {
278
			debug3("%s lastupdate %lu maxexpired %d wks time %d",
279
			    __func__, upw->upw_lastupdate, maxexpired,
280
			    (int)time(NULL));
281
			if (maxexpired != -1 && upw->upw_lastupdate +
282
			    (maxexpired*WEEK) <= time(NULL) ){
283
				log("User %.100s password expired too long",
284
				    pw->pw_name);
285
				return 0;
286
			}
287
		}
288
289
		result = passwdexpired(pw->pw_name, &msg);
290
		buffer_append(&expire_message, msg, strlen(msg));
291
		if (msg && *msg)
292
			aix_remove_embedded_newlines(msg);
293
		debug3("AIX/passwdexpired returned %d msg %.100s", result, msg);
294
295
		switch (result) {
296
			case 0: /* success, password not expired */
297
				break;
298
			case 1: /* expired, password change required */
299
				flag_password_change_required();
300
				break;
301
			default: /* user can't change(2) or other error (-1) */
302
				log("Password can't be changed for user %s: "
303
				    "%.100s", pw->pw_name, msg);
304
				if (msg)
305
					xfree(msg);
306
				return 0;
307
		}
308
		if (msg)
309
			xfree(msg);
310
229
	}
311
	}
230
#endif /* WITH_AIXAUTHENTICATE */
312
#endif /* WITH_AIXAUTHENTICATE */
231
313
Lines 241-246 Link Here
241
	return authctxt;
323
	return authctxt;
242
}
324
}
243
325
326
/*
327
 * Generate last_login message and store for later display.  This must be
328
 * called before login_login() is called and lastlog is updated.
329
 */
330
void
331
generate_login_message(const char *user, uid_t uid, const char *host)
332
{
333
#ifdef WITH_AIXAUTHENTICATE
334
	char *msg;
335
336
	/* We don't have a pty yet, so just label the line as "ssh" */
337
	if (loginsuccess(user, host, "ssh", &msg) >= 0)
338
		buffer_append(&login_message, msg, strlen(msg));
339
#elif !defined(NO_SSH_LASTLOG)
340
	if (options.print_lastlog) {
341
		char *time_string, lasthost[MAXHOSTNAMELEN], buf[256];
342
		time_t last_login_time;
343
344
		last_login_time = get_last_login_time(uid, user, lasthost,
345
		   sizeof(lasthost));
346
347
		if (last_login_time != 0) {
348
		       time_string = ctime(&last_login_time);
349
		       if (strchr(time_string, '\n'))
350
			       *strchr(time_string, '\n') = 0;
351
		       if (strcmp(lasthost, "") == 0)
352
			       snprintf(buf, sizeof(buf),
353
				   "Last login: %s\r\n",
354
				   time_string);
355
		       else
356
			       snprintf(buf, sizeof(buf),
357
				   "Last login: %s from %s\r\n",
358
				   time_string, lasthost);
359
		       buffer_append(&login_message, buf, strlen(buf));
360
		}
361
       }
362
#endif
363
}
364
244
void
365
void
245
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
366
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
246
{
367
{
Lines 268-273 Link Here
268
	    get_remote_port(),
389
	    get_remote_port(),
269
	    info);
390
	    info);
270
391
392
	if (authenticated && geteuid() == 0)
393
		generate_login_message(authctxt->user, authctxt->pw->pw_uid,
394
		    get_canonical_hostname(options.verify_reverse_mapping));
271
#ifdef WITH_AIXAUTHENTICATE
395
#ifdef WITH_AIXAUTHENTICATE
272
	if (authenticated == 0 && strcmp(method, "password") == 0)
396
	if (authenticated == 0 && strcmp(method, "password") == 0)
273
	    loginfailed(authctxt->user,
397
	    loginfailed(authctxt->user,
(-)auth.h (+4 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);
162
void	password_change_successful_handler(int);
159
163
160
char	*get_challenge(Authctxt *);
164
char	*get_challenge(Authctxt *);
161
int	verify_response(Authctxt *, const char *);
165
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
(-)loginrec.c (+1 lines)
Lines 292-297 Link Here
292
	 * reliably search wtmp(x) for the last login (see
292
	 * reliably search wtmp(x) for the last login (see
293
	 * wtmp_get_entry().)
293
	 * wtmp_get_entry().)
294
	 */
294
	 */
295
	debug("%s called euid %d", __func__, geteuid());
295
	pw = getpwuid(uid);
296
	pw = getpwuid(uid);
296
	if (pw == NULL)
297
	if (pw == NULL)
297
		fatal("login_get_lastlog: Cannot find account for uid %i", uid);
298
		fatal("login_get_lastlog: Cannot find account for uid %i", uid);
(-)session.c (-31 / +20 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-763 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
	 */
755
#ifdef USE_PAM
756
	if (is_pam_password_change_required()) {
756
	if (is_pam_password_change_required()) {
757
		print_pam_messages();
757
		print_pam_messages();
758
		do_pam_chauthtok();
758
		do_pam_chauthtok();
759
	}
759
	}
760
#endif
760
#endif
761
	buffer_append(&expire_message, "\0", 1);
762
	if (password_change_required) {
763
		printf("%s", (char *)buffer_ptr(&expire_message));
764
		do_tty_change_password(pw);
765
		password_changed = 1;
766
	}
761
767
762
	if (check_quietlogin(s, command))
768
	if (check_quietlogin(s, command))
763
		return;
769
		return;
Lines 766-788 Link Here
766
	if (!is_pam_password_change_required())
772
	if (!is_pam_password_change_required())
767
		print_pam_messages();
773
		print_pam_messages();
768
#endif /* USE_PAM */
774
#endif /* USE_PAM */
769
#ifdef WITH_AIXAUTHENTICATE
775
	if (!password_changed)
770
	if (aixloginmsg && *aixloginmsg)
776
		printf("%s", (char *)buffer_ptr(&expire_message));
771
		printf("%s\n", aixloginmsg);
777
772
#endif /* WITH_AIXAUTHENTICATE */
778
	/* display post-login message */
773
779
	buffer_append(&login_message, "\0", 1);
774
#ifndef NO_SSH_LASTLOG
780
	printf("%s", (char *)buffer_ptr(&login_message));
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
	}
785
#endif /* NO_SSH_LASTLOG */
786
781
787
	do_motd();
782
	do_motd();
788
}
783
}
Lines 1602-1613 Link Here
1602
	if (s->ttyfd != -1) {
1597
	if (s->ttyfd != -1) {
1603
		packet_disconnect("Protocol error: you already have a pty.");
1598
		packet_disconnect("Protocol error: you already have a pty.");
1604
		return 0;
1599
		return 0;
1605
	}
1606
	/* Get the time and hostname when the user last logged in. */
1607
	if (options.print_lastlog) {
1608
		s->hostname[0] = '\0';
1609
		s->last_login_time = get_last_login_time(s->pw->pw_uid,
1610
		    s->pw->pw_name, s->hostname, sizeof(s->hostname));
1611
	}
1600
	}
1612
1601
1613
	s->term = packet_get_string(&len);
1602
	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 1501-1506 Link Here
1501
	if (use_privsep)
1504
	if (use_privsep)
1502
		if ((authctxt = privsep_preauth()) != NULL)
1505
		if ((authctxt = privsep_preauth()) != NULL)
1503
			goto authenticated;
1506
			goto authenticated;
1507
1508
	/* prepare buffers to collect authentication/expiry messages */
1509
	buffer_init(&login_message);
1510
	buffer_init(&expire_message);
1504
1511
1505
	/* perform the key exchange */
1512
	/* perform the key exchange */
1506
	/* authenticate user and start session */
1513
	/* authenticate user and start session */
(-)version.h (-1 / +1 lines)
Lines 1-4 Link Here
1
/* $OpenBSD: version.h,v 1.35 2002/10/01 13:24:50 markus Exp $ */
1
/* $OpenBSD: version.h,v 1.35 2002/10/01 13:24:50 markus Exp $ */
2
2
3
#define SSH_VERSION	"OpenSSH_3.5p1"
3
#define SSH_VERSION	"OpenSSH_3.5p1-pwexp17"
4
4
(-)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