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 (-7 / +2 lines)
Lines 60-66 Link Here
60
/* states for do_pam_conversation() */
60
/* states for do_pam_conversation() */
61
enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN;
61
enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN;
62
/* remember whether pam_acct_mgmt() returned PAM_NEW_AUTHTOK_REQD */
62
/* remember whether pam_acct_mgmt() returned PAM_NEW_AUTHTOK_REQD */
63
static int password_change_required = 0;
63
extern int password_change_required;
64
/* remember whether the last pam_authenticate() succeeded or not */
64
/* remember whether the last pam_authenticate() succeeded or not */
65
static int was_authenticated = 0;
65
static int was_authenticated = 0;
66
66
Lines 260-271 Link Here
260
		case PAM_NEW_AUTHTOK_REQD:
260
		case PAM_NEW_AUTHTOK_REQD:
261
			message_cat(&__pam_msg, use_privsep ?
261
			message_cat(&__pam_msg, use_privsep ?
262
			    NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG);
262
			    NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG);
263
			/* flag that password change is necessary */
263
			flag_password_change_required();
264
			password_change_required = 1;
265
			/* disallow other functionality for now */
266
			no_port_forwarding_flag |= 2;
267
			no_agent_forwarding_flag |= 2;
268
			no_x11_forwarding_flag |= 2;
269
			break;
264
			break;
270
#endif
265
#endif
271
		default:
266
		default:
(-)auth-passwd.c (-7 / +145 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 "monitor_wrap.h"
49
#include "auth-options.h"
45
50
46
#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
51
#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
47
/* Don't need any of these headers for the PAM or SIA cases */
52
/* 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 */
86
#endif /* !USE_PAM && !HAVE_OSF_SIA */
82
87
83
extern ServerOptions options;
88
extern ServerOptions options;
84
#ifdef WITH_AIXAUTHENTICATE
89
extern Buffer login_message;
85
extern char *aixloginmsg;
90
extern int password_change_required;
86
#endif
91
pid_t password_change_pid;	/* pid used to reset forwarding flags */
87
92
88
/*
93
/*
89
 * Tries to authenticate the user using password.  Returns true if
94
 * Tries to authenticate the user using password.  Returns true if
Lines 123-128 Link Here
123
	/* deny if no user. */
128
	/* deny if no user. */
124
	if (pw == NULL)
129
	if (pw == NULL)
125
		return 0;
130
		return 0;
131
	buffer_init(&login_message);
126
#ifndef HAVE_CYGWIN
132
#ifndef HAVE_CYGWIN
127
       if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
133
       if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
128
		return 0;
134
		return 0;
Lines 149-161 Link Here
149
#endif
155
#endif
150
#ifdef WITH_AIXAUTHENTICATE
156
#ifdef WITH_AIXAUTHENTICATE
151
	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
157
	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
158
	aix_remove_embedded_newlines(authmsg);
159
160
	if (authsuccess) {
161
		char *msg;
152
162
153
	if (authsuccess)
163
		debug("authenticate() succeeded for user %s: %.100s",
164
		    pw->pw_name, authmsg);
154
	        /* We don't have a pty yet, so just label the line as "ssh" */
165
	        /* We don't have a pty yet, so just label the line as "ssh" */
155
	        if (loginsuccess(authctxt->user,
166
	        if (loginsuccess(authctxt->user,
156
			get_canonical_hostname(options.verify_reverse_mapping),
167
		    get_canonical_hostname(options.verify_reverse_mapping),
157
			"ssh", &aixloginmsg) < 0)
168
		    "ssh", &msg) < 0)
158
				aixloginmsg = NULL;
169
			msg = NULL;
170
		buffer_append(&login_message, msg, strlen(msg));
171
	} else {
172
		debug("AIX authenticate() failed for user %s: %.100s",
173
		    pw->pw_name, authmsg);
174
	}
175
	if (authmsg)
176
		xfree(authmsg);
159
177
160
	return(authsuccess);
178
	return(authsuccess);
161
#endif
179
#endif
Lines 232-235 Link Here
232
	/* Authentication is accepted if the encrypted passwords are identical. */
250
	/* Authentication is accepted if the encrypted passwords are identical. */
233
	return (strcmp(encrypted_password, pw_password) == 0);
251
	return (strcmp(encrypted_password, pw_password) == 0);
234
#endif /* !USE_PAM && !HAVE_OSF_SIA */
252
#endif /* !USE_PAM && !HAVE_OSF_SIA */
253
}
254
255
/*
256
 * Perform generic password change via tty. Like do_pam_chauthtok(),
257
 * it throws a fatal error if the password can't be changed.
258
 */
259
int
260
do_tty_change_password(struct passwd *pw)
261
{
262
	pid_t pid;
263
	int status;
264
	mysig_t old_signal;
265
266
	old_signal = mysignal(SIGCHLD, SIG_DFL);
267
268
	if ((pid = fork()) == -1)
269
		fatal("Couldn't fork: %s", strerror(errno));
270
271
	if (pid == 0) {
272
		setuid(pw->pw_uid);
273
		if (geteuid() == 0) 
274
			execl(PASSWD_PROGRAM_PATH, "passwd", pw->pw_name,
275
			    (char *)NULL);
276
		else
277
			execl(PASSWD_PROGRAM_PATH, "passwd", (char *)NULL);
278
			
279
		/* execl shouldn't return */
280
		fatal("Couldn't exec %s", PASSWD_PROGRAM_PATH);
281
		exit(1);
282
	}
283
284
	if (waitpid(pid, &status, 0) == -1)
285
		fatal("Couldn't wait for child: %s", strerror(errno));
286
	mysignal(SIGCHLD, old_signal);
287
288
	/*
289
	 * passwd sometimes returns 0 when the password has not been changed
290
	 * so we must re-test if change is still required.
291
	 */
292
	if (WIFEXITED(status) && WEXITSTATUS(status) == 0 &&
293
	    PRIVSEP(is_password_change_required(pw)) == 0) {
294
		debug("%s password changed sucessfully", __func__);
295
		flag_password_change_successful();
296
		return 1;
297
	} else {
298
		fatal("Failed to change password for %s, passwd returned %d",
299
		    pw->pw_name, status);
300
		return 0;
301
	}
302
}
303
304
/*
305
 * Checks account requires password to be changed.
306
 * 0 = no change, 1 = change reqd, 2 = can't change 
307
 */
308
int
309
is_password_change_required(struct passwd *pw)
310
{
311
	password_change_required = 0;
312
	/* re-test, sets password_change_required */
313
	if (getpwnamallow(pw->pw_name) == NULL)
314
		password_change_required = 2;
315
	debug3("%s change required %d", __func__, password_change_required);
316
	return password_change_required;
317
}
318
319
/*
320
 * Because an expired password is changed after forking to exec the user's
321
 * shell, restoring the port forwarding flags is done by sending a
322
 * USR1 signal to the parent after the password is changed successfully.
323
 */
324
void
325
flag_password_change_required(void)
326
{
327
	debug("%s disabling forwarding flags", __func__);
328
	/* flag that password change is necessary */
329
	password_change_required = 1;
330
331
	/* disallow other functionality for now */
332
	no_port_forwarding_flag |= 2;
333
	no_agent_forwarding_flag |= 2;
334
	no_x11_forwarding_flag |= 2;
335
336
	/* set handler to reset flags */
337
	password_change_pid = getpid();
338
	mysignal(SIGUSR1, password_change_successful_handler);
339
}
340
341
/*
342
 * password change successful, tell parent to restore port
343
 * forwarding flags
344
 */
345
void
346
flag_password_change_successful(void)
347
{
348
	debug("%s signalling parent to reset forwarding flags", __func__);
349
	kill(password_change_pid, SIGUSR1);
350
351
	/* reset flags in local process too */
352
	password_change_required = 0;
353
	no_port_forwarding_flag &= ~2;
354
	no_agent_forwarding_flag &= ~2;
355
	no_x11_forwarding_flag &= ~2;
356
}
357
358
/*
359
 * signal handler to reset change flags
360
 */
361
void
362
password_change_successful_handler(int sig)
363
{
364
	debug("%s restoring port forwarding flags", __func__);
365
	mysignal(SIGUSR1, SIG_DFL);     /* unset handler */
366
367
	password_change_required = 0;
368
	no_port_forwarding_flag &= ~2;
369
	no_agent_forwarding_flag &= ~2;
370
	no_x11_forwarding_flag &= ~2;
371
	if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
372
		channel_permit_all_opens();
235
}
373
}
(-)auth.c (-29 / +84 lines)
Lines 52-63 Link Here
52
#include "bufaux.h"
52
#include "bufaux.h"
53
#include "packet.h"
53
#include "packet.h"
54
54
55
#define PWCHG_FORCED	"You must change your password now.\n"
56
#define PWCHG_EXPIRED	"Your password has expired, you must change it now.\n"
57
55
/* import */
58
/* import */
56
extern ServerOptions options;
59
extern ServerOptions options;
57
60
58
/* Debugging messages */
61
/* Debugging messages */
59
Buffer auth_debug;
62
Buffer auth_debug;
60
int auth_debug_init;
63
int auth_debug_init;
64
extern int password_change_required;
65
extern Buffer expire_message;
61
66
62
/*
67
/*
63
 * Check if the user is allowed to log in via ssh. If user is listed
68
 * Check if the user is allowed to log in via ssh. If user is listed
Lines 75-87 Link Here
75
	const char *hostname = NULL, *ipaddr = NULL, *passwd;
80
	const char *hostname = NULL, *ipaddr = NULL, *passwd;
76
	char *shell;
81
	char *shell;
77
	int i;
82
	int i;
78
#ifdef WITH_AIXAUTHENTICATE
79
	char *loginmsg;
80
#endif /* WITH_AIXAUTHENTICATE */
81
#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
83
#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
82
	struct spwd *spw;
84
	struct spwd *spw;
83
#if !defined(USE_PAM) && defined(HAS_SHADOW_EXPIRE)
85
#if !defined(USE_PAM) && defined(HAS_SHADOW_EXPIRE)
84
	time_t today;
86
	time_t today, expiredate;
85
#endif
87
#endif
86
#endif
88
#endif
87
89
Lines 111-118 Link Here
111
#define	DAY		(24L * 60 * 60) /* 1 day in seconds */
113
#define	DAY		(24L * 60 * 60) /* 1 day in seconds */
112
	today = time(NULL) / DAY;
114
	today = time(NULL) / DAY;
113
	debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
115
	debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
114
	    " sp_max %d", (int)today, (int)spw->sp_expire,
116
	    " sp_max %d sp_warn %d", (int)today, (int)spw->sp_expire,
115
	    (int)spw->sp_lstchg, (int)spw->sp_max);
117
	    (int)spw->sp_lstchg, (int)spw->sp_max, (int)spw->sp_warn);
116
118
117
	/*
119
	/*
118
	 * We assume account and password expiration occurs the
120
	 * We assume account and password expiration occurs the
Lines 121-139 Link Here
121
	if (spw->sp_expire != -1 && today > spw->sp_expire) {
123
	if (spw->sp_expire != -1 && today > spw->sp_expire) {
122
		log("Account %.100s has expired", pw->pw_name);
124
		log("Account %.100s has expired", pw->pw_name);
123
		return 0;
125
		return 0;
126
	} else if (spw->sp_expire != -1 &&
127
	    spw->sp_expire - today < spw->sp_warn) {
128
		char msg[100];
129
130
		snprintf(msg, 100,
131
		    "Your account will expire in %d days.\n",
132
		    (int)(spw->sp_expire - today));
133
		buffer_append(&expire_message, msg, strlen(msg));
124
	}
134
	}
125
135
136
	expiredate = spw->sp_lstchg + spw->sp_max;
126
	if (spw->sp_lstchg == 0) {
137
	if (spw->sp_lstchg == 0) {
127
		log("User %.100s password has expired (root forced)",
138
		log("User %.100s password has expired (root forced)",
128
		    pw->pw_name);
139
		    pw->pw_name);
129
		return 0;
140
		flag_password_change_required();
130
	}
141
		buffer_append(&expire_message, PWCHG_FORCED,
131
142
		    strlen(PWCHG_FORCED));
132
	if (spw->sp_max != -1 &&
143
	} else if (spw->sp_max == -1) {
133
	    today > spw->sp_lstchg + spw->sp_max) {
144
	       debug3("%s password aging disabled", __func__);
145
	} else if (today > expiredate) {
134
		log("User %.100s password has expired (password aged)",
146
		log("User %.100s password has expired (password aged)",
135
		    pw->pw_name);
147
		    pw->pw_name);
136
		return 0;
148
		flag_password_change_required();
149
		buffer_append(&expire_message, PWCHG_EXPIRED,
150
		    strlen(PWCHG_EXPIRED));
151
	} else if (expiredate - today < spw->sp_warn) {
152
		char msg[100];
153
154
		snprintf(msg, 100,
155
		    "Your password will expire in %d days.\n",
156
		    (int)(expiredate - today));
157
		buffer_append(&expire_message, msg, strlen(msg));
137
	}
158
	}
138
#endif
159
#endif
139
160
Lines 222-248 Link Here
222
	 * PermitRootLogin to control logins via ssh), or if running as
243
	 * PermitRootLogin to control logins via ssh), or if running as
223
	 * non-root user (since loginrestrictions will always fail).
244
	 * non-root user (since loginrestrictions will always fail).
224
	 */
245
	 */
225
	if ( (pw->pw_uid != 0) && (geteuid() == 0) &&
246
	if ( (pw->pw_uid != 0) && (geteuid() == 0) ) {
226
	    loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
227
		int loginrestrict_errno = errno;
247
		int loginrestrict_errno = errno;
248
		char *msg;
228
249
229
		if (loginmsg && *loginmsg) {
250
		/* check for AIX account restrictions */
230
			/* Remove embedded newlines (if any) */
251
		if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg) != 0) {
231
			char *p;
252
			if (msg && *msg) {
232
			for (p = loginmsg; *p; p++) {
253
				aix_remove_embedded_newlines(msg);
233
				if (*p == '\n')
254
				log("Login restricted for %s: %.100s",
234
					*p = ' ';
255
				    pw->pw_name, msg);
256
				xfree(msg);
235
			}
257
			}
236
			/* Remove trailing newline */
258
237
			*--p = '\0';
259
			/* Don't fail if /etc/nologin  set */
238
			log("Login restricted for %s: %.100s", pw->pw_name, 
260
	   	 	if (!(loginrestrict_errno == EPERM && 
239
			    loginmsg);
261
			    stat(_PATH_NOLOGIN, &st) == 0))
240
		}
262
				return 0;
241
		/* Don't fail if /etc/nologin  set */
263
		}
242
	    	if (!(loginrestrict_errno == EPERM && 
243
		    stat(_PATH_NOLOGIN, &st) == 0))
244
			return 0;
245
	}
264
	}
265
266
	/*
267
	 * Check AIX password expiry.  Only check when running as root.
268
	 * Unpriv'ed users can't access /etc/security/passwd or
269
	 * /etc/security/user so passwdexpired will always fail.
270
	 */
271
	if (geteuid() == 0) {
272
		char *msg;
273
		int passexpcode;
274
275
		enduserdb();	/* flush cached results for passwdexpired */
276
		passexpcode = passwdexpired(pw->pw_name, &msg);
277
		buffer_append(&expire_message, msg, strlen(msg));
278
		if (msg && *msg)
279
			aix_remove_embedded_newlines(msg);
280
		debug("AIX passwdexpired returned %d errno %d msg %.100s",
281
		    errno, passexpcode, msg);
282
283
		switch (passexpcode) {
284
			case 0:	/* success, password not expired */
285
				break;
286
			case 1:	/* expired, password change required */
287
				flag_password_change_required();
288
				break;
289
			default: /* only admin can change (2) or other error (-1) */
290
				log("Password can't be changed for user %s: %.100s",
291
				    pw->pw_name, msg);
292
				if (msg)
293
					xfree(msg);
294
				return 0;
295
  		}
296
		if (msg)
297
			xfree(msg);
298
299
  	}
246
#endif /* WITH_AIXAUTHENTICATE */
300
#endif /* WITH_AIXAUTHENTICATE */
247
301
248
	/* We found no reason not to let this user try to log on... */
302
	/* We found no reason not to let this user try to log on... */
Lines 508-513 Link Here
508
#endif
562
#endif
509
	struct passwd *pw;
563
	struct passwd *pw;
510
564
565
	buffer_init(&expire_message);
511
	pw = getpwnam(user);
566
	pw = getpwnam(user);
512
	if (pw == NULL) {
567
	if (pw == NULL) {
513
		log("Illegal user %.100s from %.100s",
568
		log("Illegal user %.100s from %.100s",
(-)auth.h (+6 lines)
Lines 101-106 Link Here
101
101
102
int	 auth_rhosts_rsa(struct passwd *, char *, Key *);
102
int	 auth_rhosts_rsa(struct passwd *, char *, Key *);
103
int      auth_password(Authctxt *, const char *);
103
int      auth_password(Authctxt *, const char *);
104
int	 do_tty_change_password(struct passwd *pw);
105
void	 flag_password_change_required(void);
104
int      auth_rsa(struct passwd *, BIGNUM *);
106
int      auth_rsa(struct passwd *, BIGNUM *);
105
int      auth_rsa_challenge_dialog(Key *);
107
int      auth_rsa_challenge_dialog(Key *);
106
BIGNUM	*auth_rsa_generate_challenge(Key *);
108
BIGNUM	*auth_rsa_generate_challenge(Key *);
Lines 156-161 Link Here
156
158
157
int	allowed_user(struct passwd *);
159
int	allowed_user(struct passwd *);
158
struct passwd * getpwnamallow(const char *user);
160
struct passwd * getpwnamallow(const char *user);
161
int	is_password_change_required(struct passwd *);
162
void	flag_password_change_successful(void);
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 *);
Lines 183-188 Link Here
183
void	 auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
187
void	 auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
184
void	 auth_debug_send(void);
188
void	 auth_debug_send(void);
185
void	 auth_debug_reset(void);
189
void	 auth_debug_reset(void);
190
191
void	password_change_successful_handler(int);
186
192
187
#define AUTH_FAIL_MAX 6
193
#define AUTH_FAIL_MAX 6
188
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
194
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
(-)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
(-)log.c (+1 lines)
Lines 233-238 Link Here
233
		next_cu = cu->next;
233
		next_cu = cu->next;
234
		xfree(cu);
234
		xfree(cu);
235
	}
235
	}
236
	fatal_cleanups = NULL;
236
}
237
}
237
238
238
/* Cleanup and exit */
239
/* Cleanup and exit */
(-)monitor.c (+20 lines)
Lines 98-103 Link Here
98
int mm_answer_moduli(int, Buffer *);
98
int mm_answer_moduli(int, Buffer *);
99
int mm_answer_sign(int, Buffer *);
99
int mm_answer_sign(int, Buffer *);
100
int mm_answer_pwnamallow(int, Buffer *);
100
int mm_answer_pwnamallow(int, Buffer *);
101
int mm_answer_is_pwchange_reqd(int, Buffer *);
101
int mm_answer_auth2_read_banner(int, Buffer *);
102
int mm_answer_auth2_read_banner(int, Buffer *);
102
int mm_answer_authserv(int, Buffer *);
103
int mm_answer_authserv(int, Buffer *);
103
int mm_answer_authpassword(int, Buffer *);
104
int mm_answer_authpassword(int, Buffer *);
Lines 183-188 Link Here
183
    {MONITOR_REQ_PTY, 0, mm_answer_pty},
184
    {MONITOR_REQ_PTY, 0, mm_answer_pty},
184
    {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
185
    {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
185
    {MONITOR_REQ_TERM, 0, mm_answer_term},
186
    {MONITOR_REQ_TERM, 0, mm_answer_term},
187
    {MONITOR_REQ_PWCHANGE_REQD, 0, mm_answer_is_pwchange_reqd},
186
    {0, 0, NULL}
188
    {0, 0, NULL}
187
};
189
};
188
190
Lines 219-224 Link Here
219
    {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
221
    {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
220
    {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
222
    {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
221
    {MONITOR_REQ_TERM, 0, mm_answer_term},
223
    {MONITOR_REQ_TERM, 0, mm_answer_term},
224
    {MONITOR_REQ_PWCHANGE_REQD, 0, mm_answer_is_pwchange_reqd},
222
    {0, 0, NULL}
225
    {0, 0, NULL}
223
};
226
};
224
227
Lines 320-329 Link Here
320
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
323
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
321
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
324
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
322
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
325
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
326
		monitor_permit(mon_dispatch, MONITOR_REQ_PWCHANGE_REQD, 1);
323
327
324
	} else {
328
	} else {
325
		mon_dispatch = mon_dispatch_postauth15;
329
		mon_dispatch = mon_dispatch_postauth15;
326
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
330
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
331
		monitor_permit(mon_dispatch, MONITOR_REQ_PWCHANGE_REQD, 1);
327
	}
332
	}
328
	if (!no_pty_flag) {
333
	if (!no_pty_flag) {
329
		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
334
		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
Lines 558-563 Link Here
558
#ifdef USE_PAM
563
#ifdef USE_PAM
559
	monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
564
	monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
560
#endif
565
#endif
566
567
	return (0);
568
}
569
570
int
571
mm_answer_is_pwchange_reqd(int socket, Buffer *m)
572
{
573
	int required;
574
575
	buffer_clear(m);
576
	required = is_password_change_required(authctxt->pw);
577
	buffer_put_int(m, required);
578
579
	debug3("%s: sending MONITOR_ANS_PWCHANGE_REQD: %d", __func__, required);
580
	mm_request_send(socket, MONITOR_ANS_PWCHANGE_REQD, m);
561
581
562
	return (0);
582
	return (0);
563
}
583
}
(-)monitor.h (+1 lines)
Lines 33-38 Link Here
33
	MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
33
	MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
34
	MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
34
	MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
35
	MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
35
	MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
36
	MONITOR_REQ_PWCHANGE_REQD, MONITOR_ANS_PWCHANGE_REQD,
36
	MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
37
	MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
37
	MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
38
	MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
38
	MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
39
	MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
(-)monitor_wrap.c (+18 lines)
Lines 207-212 Link Here
207
	return (pw);
207
	return (pw);
208
}
208
}
209
209
210
int
211
mm_is_password_change_required(struct passwd *pw)
212
{
213
	Buffer m;
214
	int result;
215
216
	debug3("%s entering", __func__);
217
	buffer_init(&m);
218
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWCHANGE_REQD, &m);
219
	buffer_clear(&m);
220
	mm_request_receive_expect(pmonitor->m_recvfd,
221
	    MONITOR_ANS_PWCHANGE_REQD, &m);
222
	result = buffer_get_int(&m);
223
	buffer_free(&m);
224
225
	return (result);
226
}
227
210
char *mm_auth2_read_banner(void)
228
char *mm_auth2_read_banner(void)
211
{
229
{
212
	Buffer m;
230
	Buffer m;
(-)monitor_wrap.h (+1 lines)
Lines 44-49 Link Here
44
int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
44
int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
45
void mm_inform_authserv(char *, char *);
45
void mm_inform_authserv(char *, char *);
46
struct passwd *mm_getpwnamallow(const char *);
46
struct passwd *mm_getpwnamallow(const char *);
47
int mm_is_password_change_required(struct passwd *);
47
char *mm_auth2_read_banner(void);
48
char *mm_auth2_read_banner(void);
48
int mm_auth_password(struct Authctxt *, char *);
49
int mm_auth_password(struct Authctxt *, char *);
49
int mm_key_allowed(enum mm_keytype, char *, char *, Key *);
50
int mm_key_allowed(enum mm_keytype, char *, char *, Key *);
(-)session.c (-11 / +20 lines)
Lines 102-111 Link Here
102
/* data */
102
/* data */
103
#define MAX_SESSIONS 10
103
#define MAX_SESSIONS 10
104
Session	sessions[MAX_SESSIONS];
104
Session	sessions[MAX_SESSIONS];
105
105
Buffer expire_message;	/* "password will expire/has expired" messages */
106
#ifdef WITH_AIXAUTHENTICATE
106
Buffer login_message;	/* message to be displayed after login */
107
char *aixloginmsg;
107
int password_change_required = 0;
108
#endif /* WITH_AIXAUTHENTICATE */
109
108
110
#ifdef HAVE_LOGIN_CAP
109
#ifdef HAVE_LOGIN_CAP
111
login_cap_t *lc;
110
login_cap_t *lc;
Lines 456-465 Link Here
456
#if defined(USE_PAM)
455
#if defined(USE_PAM)
457
	do_pam_session(s->pw->pw_name, NULL);
456
	do_pam_session(s->pw->pw_name, NULL);
458
	do_pam_setcred(1);
457
	do_pam_setcred(1);
459
	if (is_pam_password_change_required())
458
#endif /* USE_PAM */
459
460
	if (password_change_required)
460
		packet_disconnect("Password change required but no "
461
		packet_disconnect("Password change required but no "
461
		    "TTY available");
462
		    "TTY available");
462
#endif /* USE_PAM */
463
463
464
	/* Fork the child. */
464
	/* Fork the child. */
465
	if ((pid = fork()) == 0) {
465
	if ((pid = fork()) == 0) {
Lines 723-728 Link Here
723
	socklen_t fromlen;
723
	socklen_t fromlen;
724
	struct sockaddr_storage from;
724
	struct sockaddr_storage from;
725
	struct passwd * pw = s->pw;
725
	struct passwd * pw = s->pw;
726
	int password_changed = 0;
726
	pid_t pid = getpid();
727
	pid_t pid = getpid();
727
728
728
	/*
729
	/*
Lines 746-761 Link Here
746
		    options.verify_reverse_mapping),
747
		    options.verify_reverse_mapping),
747
		    (struct sockaddr *)&from, fromlen);
748
		    (struct sockaddr *)&from, fromlen);
748
749
749
#ifdef USE_PAM
750
	/*
750
	/*
751
	 * If password change is needed, do it now.
751
	 * If password change is needed, do it now.
752
	 * This needs to occur before the ~/.hushlogin check.
752
	 * This needs to occur before the ~/.hushlogin check.
753
	 */
753
	 */
754
#ifdef USE_PAM
754
	if (is_pam_password_change_required()) {
755
	if (is_pam_password_change_required()) {
755
		print_pam_messages();
756
		print_pam_messages();
756
		do_pam_chauthtok();
757
		do_pam_chauthtok();
757
	}
758
	}
758
#endif
759
#endif
760
	buffer_append(&expire_message, "\0", 1);
761
	if (password_change_required) {
762
		puts((char *)buffer_ptr(&expire_message));
763
		do_tty_change_password(pw);
764
		password_changed = 1;
765
	}
759
766
760
	if (check_quietlogin(s, command))
767
	if (check_quietlogin(s, command))
761
		return;
768
		return;
Lines 764-773 Link Here
764
	if (!is_pam_password_change_required())
771
	if (!is_pam_password_change_required())
765
		print_pam_messages();
772
		print_pam_messages();
766
#endif /* USE_PAM */
773
#endif /* USE_PAM */
767
#ifdef WITH_AIXAUTHENTICATE
774
	if (!password_changed)
768
	if (aixloginmsg && *aixloginmsg)
775
		printf("%s", (char *)buffer_ptr(&expire_message));
769
		printf("%s\n", aixloginmsg);
776
770
#endif /* WITH_AIXAUTHENTICATE */
777
	/* display post-login message */
778
	buffer_append(&login_message, "\0", 1);
779
	puts((char *)buffer_ptr(&login_message));
771
780
772
#ifndef NO_SSH_LASTLOG
781
#ifndef NO_SSH_LASTLOG
773
	if (options.print_lastlog && s->last_login_time != 0) {
782
	if (options.print_lastlog && s->last_login_time != 0) {
(-)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 26-29 Link Here
26
26
27
#ifdef _AIX
27
#ifdef _AIX
28
void aix_usrinfo(struct passwd *pw);
28
void aix_usrinfo(struct passwd *pw);
29
void aix_remove_embedded_newlines(char *);
29
#endif /* _AIX */
30
#endif /* _AIX */

Return to bug 14