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

Collapse All | Expand All

(-)a/auth-pam.c (-5 / +8 lines)
Lines 670-675 sshpam_init_ctx(Authctxt *authctxt) Link Here
670
{
670
{
671
	struct pam_ctxt *ctxt;
671
	struct pam_ctxt *ctxt;
672
	int socks[2];
672
	int socks[2];
673
	char *auth_info;
673
674
674
	debug3("PAM: %s entering", __func__);
675
	debug3("PAM: %s entering", __func__);
675
	/*
676
	/*
Lines 685-690 sshpam_init_ctx(Authctxt *authctxt) Link Here
685
		return (NULL);
686
		return (NULL);
686
	}
687
	}
687
688
689
	if (authctxt->session_info != NULL &&
690
	    (auth_info = sshbuf_dup_string(authctxt->session_info)) != NULL) {
691
		do_pam_putenv("SSH_USER_AUTH", auth_info);
692
		free(auth_info);
693
	}
694
688
	ctxt = xcalloc(1, sizeof *ctxt);
695
	ctxt = xcalloc(1, sizeof *ctxt);
689
696
690
	/* Start the authentication thread */
697
	/* Start the authentication thread */
Lines 1091-1102 do_pam_putenv(char *name, char *value) Link Here
1091
	int ret = 1;
1098
	int ret = 1;
1092
#ifdef HAVE_PAM_PUTENV
1099
#ifdef HAVE_PAM_PUTENV
1093
	char *compound;
1100
	char *compound;
1094
	size_t len;
1095
1096
	len = strlen(name) + strlen(value) + 2;
1097
	compound = xmalloc(len);
1098
1101
1099
	snprintf(compound, len, "%s=%s", name, value);
1102
	xasprintf(&compound, "%s=%s", name, value);
1100
	ret = pam_putenv(sshpam_handle, compound);
1103
	ret = pam_putenv(sshpam_handle, compound);
1101
	free(compound);
1104
	free(compound);
1102
#endif
1105
#endif
(-)a/auth.c (-17 / +43 lines)
Lines 267-287 allowed_user(struct passwd * pw) Link Here
267
	return 1;
267
	return 1;
268
}
268
}
269
269
270
void
270
/*
271
auth_info(Authctxt *authctxt, const char *fmt, ...)
271
 * Formats any key left in authctxt->auth_method_key for inclusion in
272
 * auth_log()'s message. Also includes authxtct->auth_method_info if present.
273
 */
274
static char *
275
format_method_key(Authctxt *authctxt)
272
{
276
{
273
	va_list ap;
277
	const struct sshkey *key = authctxt->auth_method_key;
274
        int i;
278
	const char *methinfo = authctxt->auth_method_info;
275
279
	char *fp, *ret = NULL;
276
	free(authctxt->info);
277
	authctxt->info = NULL;
278
280
279
	va_start(ap, fmt);
281
	if (key == NULL)
280
	i = vasprintf(&authctxt->info, fmt, ap);
282
		return NULL;
281
	va_end(ap);
282
283
283
	if (i < 0 || authctxt->info == NULL)
284
	if (key_is_cert(key)) {
284
		fatal("vasprintf failed");
285
		fp = sshkey_fingerprint(key->cert->signature_key,
286
		    options.fingerprint_hash, SSH_FP_DEFAULT);
287
		xasprintf(&ret, "%s ID %s (serial %llu) CA %s %s%s%s", 
288
		    sshkey_type(key), key->cert->key_id,
289
		    (unsigned long long)key->cert->serial,
290
		    sshkey_type(key->cert->signature_key),
291
		    fp == NULL ? "(null)" : fp,
292
		    methinfo == NULL ? "" : ", ",
293
		    methinfo == NULL ? "" : methinfo);
294
		free(fp);
295
	} else {
296
		fp = sshkey_fingerprint(key, options.fingerprint_hash,
297
		    SSH_FP_DEFAULT);
298
		xasprintf(&ret, "%s %s%s%s", sshkey_type(key),
299
		    fp == NULL ? "(null)" : fp,
300
		    methinfo == NULL ? "" : ", ",
301
		    methinfo == NULL ? "" : methinfo);
302
		free(fp);
303
	}
304
	return ret;
285
}
305
}
286
306
287
void
307
void
Lines 290-296 auth_log(Authctxt *authctxt, int authenticated, int partial, Link Here
290
{
310
{
291
	struct ssh *ssh = active_state; /* XXX */
311
	struct ssh *ssh = active_state; /* XXX */
292
	void (*authlog) (const char *fmt,...) = verbose;
312
	void (*authlog) (const char *fmt,...) = verbose;
293
	char *authmsg;
313
	const char *authmsg;
314
	char *extra = NULL;
294
315
295
	if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
316
	if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
296
		return;
317
		return;
Lines 309-314 auth_log(Authctxt *authctxt, int authenticated, int partial, Link Here
309
	else
330
	else
310
		authmsg = authenticated ? "Accepted" : "Failed";
331
		authmsg = authenticated ? "Accepted" : "Failed";
311
332
333
	if ((extra = format_method_key(authctxt)) == NULL) {
334
		if (authctxt->auth_method_info != NULL)
335
			extra = xstrdup(authctxt->auth_method_info);
336
	}
337
312
	authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
338
	authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
313
	    authmsg,
339
	    authmsg,
314
	    method,
340
	    method,
Lines 317-326 auth_log(Authctxt *authctxt, int authenticated, int partial, Link Here
317
	    authctxt->user,
343
	    authctxt->user,
318
	    ssh_remote_ipaddr(ssh),
344
	    ssh_remote_ipaddr(ssh),
319
	    ssh_remote_port(ssh),
345
	    ssh_remote_port(ssh),
320
	    authctxt->info != NULL ? ": " : "",
346
	    extra != NULL ? ": " : "",
321
	    authctxt->info != NULL ? authctxt->info : "");
347
	    extra != NULL ? extra : "");
322
	free(authctxt->info);
323
	authctxt->info = NULL;
324
348
325
#ifdef CUSTOM_FAILED_LOGIN
349
#ifdef CUSTOM_FAILED_LOGIN
326
	if (authenticated == 0 && !authctxt->postponed &&
350
	if (authenticated == 0 && !authctxt->postponed &&
Lines 340-345 auth_log(Authctxt *authctxt, int authenticated, int partial, Link Here
340
	if (authenticated == 0 && !authctxt->postponed)
364
	if (authenticated == 0 && !authctxt->postponed)
341
		audit_event(audit_classify_auth(method));
365
		audit_event(audit_classify_auth(method));
342
#endif
366
#endif
367
368
	free(extra);
343
}
369
}
344
370
345
371
(-)a/auth.h (-14 / +30 lines)
Lines 62-74 struct Authctxt { Link Here
62
	char		*service;
62
	char		*service;
63
	struct passwd	*pw;		/* set if 'valid' */
63
	struct passwd	*pw;		/* set if 'valid' */
64
	char		*style;
64
	char		*style;
65
66
	/* Method lists for multiple authentication */
67
	char		**auth_methods;	/* modified from server config */
68
	u_int		 num_auth_methods;
69
70
	/* Authentication method-specific data */
71
	void		*methoddata;
65
	void		*kbdintctxt;
72
	void		*kbdintctxt;
66
	char		*info;		/* Extra info for next auth_log */
67
#ifdef BSD_AUTH
73
#ifdef BSD_AUTH
68
	auth_session_t	*as;
74
	auth_session_t	*as;
69
#endif
75
#endif
70
	char		**auth_methods;	/* modified from server config */
71
	u_int		 num_auth_methods;
72
#ifdef KRB5
76
#ifdef KRB5
73
	krb5_context	 krb5_ctx;
77
	krb5_context	 krb5_ctx;
74
	krb5_ccache	 krb5_fwd_ccache;
78
	krb5_ccache	 krb5_fwd_ccache;
Lines 76-86 struct Authctxt { Link Here
76
	char		*krb5_ticket_file;
80
	char		*krb5_ticket_file;
77
	char		*krb5_ccname;
81
	char		*krb5_ccname;
78
#endif
82
#endif
79
	Buffer		*loginmsg;
80
	void		*methoddata;
81
83
82
	struct sshkey	**prev_userkeys;
84
	/* Authentication keys already used; these will be refused henceforth */
83
	u_int		 nprev_userkeys;
85
	struct sshkey	**prev_keys;
86
	u_int		 nprev_keys;
87
88
	/* Last used key and ancilliary information from active auth method */
89
	struct sshkey	*auth_method_key;
90
	char		*auth_method_info;
91
92
	/* Information exposed to session */
93
	Buffer		*loginmsg;	/* Messages to be displayed to pty */
94
	struct sshbuf	*session_info;	/* Auth info for environment */
84
};
95
};
85
/*
96
/*
86
 * Every authentication method has to handle authentication requests for
97
 * Every authentication method has to handle authentication requests for
Lines 119-128 int auth_password(Authctxt *, const char *); Link Here
119
130
120
int	 hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
131
int	 hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
121
int	 user_key_allowed(struct passwd *, Key *, int);
132
int	 user_key_allowed(struct passwd *, Key *, int);
122
void	 pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
133
int	 auth2_key_already_used(Authctxt *, const struct sshkey *);
123
	    __attribute__((__format__ (printf, 3, 4)));
134
124
void	 auth2_record_userkey(Authctxt *, struct sshkey *);
135
/*
125
int	 auth2_userkey_already_used(Authctxt *, struct sshkey *);
136
 * Handling auth method-specific information for logging and prevention
137
 * of key reuse during multiple authentication.
138
 */
139
void	 auth2_authctxt_reset_info(Authctxt *);
140
void	 auth2_record_key(Authctxt *, int, const struct sshkey *);
141
void	 auth2_record_info(Authctxt *authctxt, const char *, ...)
142
	    __attribute__((__format__ (printf, 2, 3)))
143
	    __attribute__((__nonnull__ (2)));
144
void	 auth2_update_session_info(Authctxt *, const char *, const char *);
126
145
127
struct stat;
146
struct stat;
128
int	 auth_secure_path(const char *, struct stat *, const char *, uid_t,
147
int	 auth_secure_path(const char *, struct stat *, const char *, uid_t,
Lines 149-157 void disable_forwarding(void); Link Here
149
168
150
void	do_authentication2(Authctxt *);
169
void	do_authentication2(Authctxt *);
151
170
152
void	auth_info(Authctxt *authctxt, const char *, ...)
153
	    __attribute__((__format__ (printf, 2, 3)))
154
	    __attribute__((__nonnull__ (2)));
155
void	auth_log(Authctxt *, int, int, const char *, const char *);
171
void	auth_log(Authctxt *, int, int, const char *, const char *);
156
void	auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
172
void	auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
157
void	userauth_finish(Authctxt *, int, const char *, const char *);
173
void	userauth_finish(Authctxt *, int, const char *, const char *);
(-)a/auth2-gss.c (+10 lines)
Lines 227-232 input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) Link Here
227
{
227
{
228
	Authctxt *authctxt = ctxt;
228
	Authctxt *authctxt = ctxt;
229
	int authenticated;
229
	int authenticated;
230
	const char *displayname;
230
231
231
	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
232
	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
232
		fatal("No authentication or GSSAPI context");
233
		fatal("No authentication or GSSAPI context");
Lines 240-245 input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) Link Here
240
241
241
	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
242
	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
242
243
244
	if ((!use_privsep || mm_is_monitor()) &&
245
	    (displayname = ssh_gssapi_displayname()) != NULL)
246
		auth2_record_info(authctxt, "%s", displayname);
247
243
	authctxt->postponed = 0;
248
	authctxt->postponed = 0;
244
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
249
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
245
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
250
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
Lines 258-263 input_gssapi_mic(int type, u_int32_t plen, void *ctxt) Link Here
258
	Buffer b;
263
	Buffer b;
259
	gss_buffer_desc mic, gssbuf;
264
	gss_buffer_desc mic, gssbuf;
260
	u_int len;
265
	u_int len;
266
	const char *displayname;
261
267
262
	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
268
	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
263
		fatal("No authentication or GSSAPI context");
269
		fatal("No authentication or GSSAPI context");
Lines 281-286 input_gssapi_mic(int type, u_int32_t plen, void *ctxt) Link Here
281
	buffer_free(&b);
287
	buffer_free(&b);
282
	free(mic.value);
288
	free(mic.value);
283
289
290
	if ((!use_privsep || mm_is_monitor()) &&
291
	    (displayname = ssh_gssapi_displayname()) != NULL)
292
		auth2_record_info(authctxt, "%s", displayname);
293
284
	authctxt->postponed = 0;
294
	authctxt->postponed = 0;
285
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
295
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
286
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
296
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
(-)a/auth2-hostbased.c (-5 / +5 lines)
Lines 132-152 userauth_hostbased(Authctxt *authctxt) Link Here
132
	buffer_dump(&b);
132
	buffer_dump(&b);
133
#endif
133
#endif
134
134
135
	pubkey_auth_info(authctxt, key,
135
	auth2_record_info(authctxt,
136
	    "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
136
	    "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
137
137
138
	/* test for allowed key and correct signature */
138
	/* test for allowed key and correct signature */
139
	authenticated = 0;
139
	authenticated = 0;
140
	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
140
	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
141
	    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
141
	    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
142
			buffer_len(&b))) == 1)
142
	    buffer_len(&b))) == 1)
143
		authenticated = 1;
143
		authenticated = 1;
144
144
145
	auth2_record_key(authctxt, authenticated, key);
145
	buffer_free(&b);
146
	buffer_free(&b);
146
done:
147
done:
147
	debug2("userauth_hostbased: authenticated %d", authenticated);
148
	debug2("%s: authenticated %d", __func__, authenticated);
148
	if (key != NULL)
149
	sshkey_free(key);
149
		key_free(key);
150
	free(pkalg);
150
	free(pkalg);
151
	free(pkblob);
151
	free(pkblob);
152
	free(cuser);
152
	free(cuser);
(-)a/auth2-pubkey.c (-74 / +3 lines)
Lines 127-133 userauth_pubkey(Authctxt *authctxt) Link Here
127
		goto done;
127
		goto done;
128
	}
128
	}
129
	fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
129
	fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
130
	if (auth2_userkey_already_used(authctxt, key)) {
130
	if (auth2_key_already_used(authctxt, key)) {
131
		logit("refusing previously-used %s key", key_type(key));
131
		logit("refusing previously-used %s key", key_type(key));
132
		goto done;
132
		goto done;
133
	}
133
	}
Lines 171-177 userauth_pubkey(Authctxt *authctxt) Link Here
171
#ifdef DEBUG_PK
171
#ifdef DEBUG_PK
172
		buffer_dump(&b);
172
		buffer_dump(&b);
173
#endif
173
#endif
174
		pubkey_auth_info(authctxt, key, NULL);
175
174
176
		/* test for correct signature */
175
		/* test for correct signature */
177
		authenticated = 0;
176
		authenticated = 0;
Lines 179-190 userauth_pubkey(Authctxt *authctxt) Link Here
179
		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
178
		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
180
		    buffer_len(&b))) == 1) {
179
		    buffer_len(&b))) == 1) {
181
			authenticated = 1;
180
			authenticated = 1;
182
			/* Record the successful key to prevent reuse */
183
			auth2_record_userkey(authctxt, key);
184
			key = NULL; /* Don't free below */
185
		}
181
		}
186
		buffer_free(&b);
182
		buffer_free(&b);
187
		free(sig);
183
		free(sig);
184
		auth2_record_key(authctxt, authenticated, key);
188
	} else {
185
	} else {
189
		debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
186
		debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
190
		    __func__, sshkey_type(key), fp);
187
		    __func__, sshkey_type(key), fp);
Lines 211-261 userauth_pubkey(Authctxt *authctxt) Link Here
211
		auth_clear_options();
208
		auth_clear_options();
212
done:
209
done:
213
	debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
210
	debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
214
	if (key != NULL)
211
	sshkey_free(key);
215
		key_free(key);
216
	free(pkalg);
212
	free(pkalg);
217
	free(pkblob);
213
	free(pkblob);
218
	free(fp);
214
	free(fp);
219
	return authenticated;
215
	return authenticated;
220
}
216
}
221
217
222
void
223
pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
224
{
225
	char *fp, *extra;
226
	va_list ap;
227
	int i;
228
229
	extra = NULL;
230
	if (fmt != NULL) {
231
		va_start(ap, fmt);
232
		i = vasprintf(&extra, fmt, ap);
233
		va_end(ap);
234
		if (i < 0 || extra == NULL)
235
			fatal("%s: vasprintf failed", __func__);	
236
	}
237
238
	if (key_is_cert(key)) {
239
		fp = sshkey_fingerprint(key->cert->signature_key,
240
		    options.fingerprint_hash, SSH_FP_DEFAULT);
241
		auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 
242
		    key_type(key), key->cert->key_id,
243
		    (unsigned long long)key->cert->serial,
244
		    key_type(key->cert->signature_key),
245
		    fp == NULL ? "(null)" : fp,
246
		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
247
		free(fp);
248
	} else {
249
		fp = sshkey_fingerprint(key, options.fingerprint_hash,
250
		    SSH_FP_DEFAULT);
251
		auth_info(authctxt, "%s %s%s%s", key_type(key),
252
		    fp == NULL ? "(null)" : fp,
253
		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
254
		free(fp);
255
	}
256
	free(extra);
257
}
258
259
/*
218
/*
260
 * Splits 's' into an argument vector. Handles quoted string and basic
219
 * Splits 's' into an argument vector. Handles quoted string and basic
261
 * escape characters (\\, \", \'). Caller must free the argument vector
220
 * escape characters (\\, \", \'). Caller must free the argument vector
Lines 1119-1154 user_key_allowed(struct passwd *pw, Key *key, int auth_attempt) Link Here
1119
1078
1120
	return success;
1079
	return success;
1121
}
1080
}
1122
1123
/* Records a public key in the list of previously-successful keys */
1124
void
1125
auth2_record_userkey(Authctxt *authctxt, struct sshkey *key)
1126
{
1127
	struct sshkey **tmp;
1128
1129
	if (authctxt->nprev_userkeys >= INT_MAX ||
1130
	    (tmp = reallocarray(authctxt->prev_userkeys,
1131
	    authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL)
1132
		fatal("%s: reallocarray failed", __func__);
1133
	authctxt->prev_userkeys = tmp;
1134
	authctxt->prev_userkeys[authctxt->nprev_userkeys] = key;
1135
	authctxt->nprev_userkeys++;
1136
}
1137
1138
/* Checks whether a key has already been used successfully for authentication */
1139
int
1140
auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key)
1141
{
1142
	u_int i;
1143
1144
	for (i = 0; i < authctxt->nprev_userkeys; i++) {
1145
		if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) {
1146
			return 1;
1147
		}
1148
	}
1149
	return 0;
1150
}
1151
1152
Authmethod method_pubkey = {
1081
Authmethod method_pubkey = {
1153
	"publickey",
1082
	"publickey",
1154
	userauth_pubkey,
1083
	userauth_pubkey,
(-)a/auth2.c (+131 lines)
Lines 50-55 Link Here
50
#include "dispatch.h"
50
#include "dispatch.h"
51
#include "pathnames.h"
51
#include "pathnames.h"
52
#include "buffer.h"
52
#include "buffer.h"
53
#include "ssherr.h"
53
54
54
#ifdef GSSAPI
55
#ifdef GSSAPI
55
#include "ssh-gss.h"
56
#include "ssh-gss.h"
Lines 275-280 input_userauth_request(int type, u_int32_t seq, void *ctxt) Link Here
275
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
276
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
276
#endif
277
#endif
277
278
279
	auth2_authctxt_reset_info(authctxt);
278
	authctxt->postponed = 0;
280
	authctxt->postponed = 0;
279
	authctxt->server_caused_failure = 0;
281
	authctxt->server_caused_failure = 0;
280
282
Lines 322-327 userauth_finish(Authctxt *authctxt, int authenticated, const char *method, Link Here
322
		}
324
		}
323
	}
325
	}
324
326
327
	/* Update information exposed to session */
328
	if (authenticated || partial)
329
		auth2_update_session_info(authctxt, method, submethod);
330
325
	/* Log before sending the reply */
331
	/* Log before sending the reply */
326
	auth_log(authctxt, authenticated, partial, method, submethod);
332
	auth_log(authctxt, authenticated, partial, method, submethod);
327
333
Lines 622-625 auth2_update_methods_lists(Authctxt *authctxt, const char *method, Link Here
622
	return 0;
628
	return 0;
623
}
629
}
624
630
631
/* Reset method-specific information */
632
void auth2_authctxt_reset_info(Authctxt *authctxt)
633
{
634
	sshkey_free(authctxt->auth_method_key);
635
	free(authctxt->auth_method_info);
636
	authctxt->auth_method_key = NULL;
637
	authctxt->auth_method_info = NULL;
638
}
639
640
/* Record auth method-specific information for logs */
641
void
642
auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
643
{
644
	va_list ap;
645
        int i;
646
647
	free(authctxt->auth_method_info);
648
	authctxt->auth_method_info = NULL;
649
650
	va_start(ap, fmt);
651
	i = vasprintf(&authctxt->auth_method_info, fmt, ap);
652
	va_end(ap);
653
654
	if (i < 0 || authctxt->auth_method_info == NULL)
655
		fatal("%s: vasprintf failed", __func__);
656
}
657
658
/*
659
 * Records a public key used in authentication. This is used for logging
660
 * and to ensure that the same key is not subsequently accepted again for
661
 * multiple authentication.
662
 */
663
void
664
auth2_record_key(Authctxt *authctxt, int authenticated,
665
    const struct sshkey *key)
666
{
667
	struct sshkey **tmp, *dup;
668
	int r;
669
670
	if ((r = sshkey_demote(key, &dup)) != 0)
671
		fatal("%s: copy key: %s", __func__, ssh_err(r));
672
	sshkey_free(authctxt->auth_method_key);
673
	authctxt->auth_method_key = dup;
674
675
	if (!authenticated)
676
		return;
677
678
	/* If authenticated, make sure we don't accept this key again */
679
	if ((r = sshkey_demote(key, &dup)) != 0)
680
		fatal("%s: copy key: %s", __func__, ssh_err(r));
681
	if (authctxt->nprev_keys >= INT_MAX ||
682
	    (tmp = reallocarray(authctxt->prev_keys, authctxt->nprev_keys + 1,
683
	    sizeof(*authctxt->prev_keys))) == NULL)
684
		fatal("%s: reallocarray failed", __func__);
685
	authctxt->prev_keys = tmp;
686
	authctxt->prev_keys[authctxt->nprev_keys] = dup;
687
	authctxt->nprev_keys++;
688
689
}
690
691
/* Checks whether a key has already been previously used for authentication */
692
int
693
auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
694
{
695
	u_int i;
696
	char *fp;
697
698
	for (i = 0; i < authctxt->nprev_keys; i++) {
699
		if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
700
			fp = sshkey_fingerprint(authctxt->prev_keys[i],
701
			    options.fingerprint_hash, SSH_FP_DEFAULT);
702
			debug3("%s: key already used: %s %s", __func__,
703
			    sshkey_type(authctxt->prev_keys[i]),
704
			    fp == NULL ? "UNKNOWN" : fp);
705
			free(fp);
706
			return 1;
707
		}
708
	}
709
	return 0;
710
}
711
712
/*
713
 * Updates authctxt->session_info with details of authentication. Should be
714
 * whenever an authentication method succeeds.
715
 */
716
void
717
auth2_update_session_info(Authctxt *authctxt, const char *method,
718
    const char *submethod)
719
{
720
	int r;
721
722
	/* Prepare or append to session info buffer */
723
	if (authctxt->session_info == NULL) {
724
		if ((authctxt->session_info = sshbuf_new()) == NULL)
725
			fatal("%s: sshbuf_new", __func__);
726
	} else if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
727
		fatal("%s: append: %s", __func__, ssh_err(r));
728
729
	/* Append method[/submethod] */
730
	if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
731
	    method, submethod == NULL ? "" : "/",
732
	    submethod == NULL ? "" : submethod)) != 0)
733
		fatal("%s: append method: %s", __func__, ssh_err(r));
734
735
	/* Append key if present */
736
	if (authctxt->auth_method_key != NULL) {
737
		if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
738
		    (r = sshkey_format_text(authctxt->auth_method_key,
739
		    authctxt->session_info)) != 0)
740
			fatal("%s: append key: %s", __func__, ssh_err(r));
741
	}
742
743
	if (authctxt->auth_method_info != NULL) {
744
		/* Ensure no ambiguity here */
745
		if (strchr(authctxt->auth_method_info, '\n') != NULL)
746
			fatal("%s: auth_method_info contains \\n", __func__);
747
		if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
748
		    (r = sshbuf_putf(authctxt->session_info, "%s",
749
		    authctxt->auth_method_info)) != 0) {
750
			fatal("%s: append method info: %s",
751
			    __func__, ssh_err(r));
752
		}
753
	}
754
	auth2_authctxt_reset_info(authctxt);
755
}
625
756
(-)a/gss-serv.c (+9 lines)
Lines 393-396 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) Link Here
393
	return (ctx->major);
393
	return (ctx->major);
394
}
394
}
395
395
396
/* Privileged */
397
const char *ssh_gssapi_displayname(void)
398
{
399
	if (gssapi_client.displayname.length == 0 ||
400
	    gssapi_client.displayname.value == NULL)
401
		return NULL;
402
	return (char *)gssapi_client.displayname.value;
403
}
404
396
#endif
405
#endif
(-)a/monitor.c (-17 / +23 lines)
Lines 308-313 monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) Link Here
308
		partial = 0;
308
		partial = 0;
309
		auth_method = "unknown";
309
		auth_method = "unknown";
310
		auth_submethod = NULL;
310
		auth_submethod = NULL;
311
		auth2_authctxt_reset_info(authctxt);
312
311
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
313
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
312
314
313
		/* Special handling for multiple required authentications */
315
		/* Special handling for multiple required authentications */
Lines 343-348 monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) Link Here
343
#endif
345
#endif
344
		}
346
		}
345
		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
347
		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
348
			if (authenticated || partial) {
349
				auth2_update_session_info(authctxt,
350
				    auth_method, auth_submethod);
351
			}
346
			auth_log(authctxt, authenticated, partial,
352
			auth_log(authctxt, authenticated, partial,
347
			    auth_method, auth_submethod);
353
			    auth_method, auth_submethod);
348
			if (!partial && !authenticated)
354
			if (!partial && !authenticated)
Lines 1147-1170 mm_answer_keyallowed(int sock, Buffer *m) Link Here
1147
		switch (type) {
1153
		switch (type) {
1148
		case MM_USERKEY:
1154
		case MM_USERKEY:
1149
			allowed = options.pubkey_authentication &&
1155
			allowed = options.pubkey_authentication &&
1150
			    !auth2_userkey_already_used(authctxt, key) &&
1156
			    !auth2_key_already_used(authctxt, key) &&
1151
			    match_pattern_list(sshkey_ssh_name(key),
1157
			    match_pattern_list(sshkey_ssh_name(key),
1152
			    options.pubkey_key_types, 0) == 1 &&
1158
			    options.pubkey_key_types, 0) == 1 &&
1153
			    user_key_allowed(authctxt->pw, key,
1159
			    user_key_allowed(authctxt->pw, key,
1154
			    pubkey_auth_attempt);
1160
			    pubkey_auth_attempt);
1155
			pubkey_auth_info(authctxt, key, NULL);
1156
			auth_method = "publickey";
1161
			auth_method = "publickey";
1162
			auth2_record_key(authctxt, 0, key);
1157
			if (options.pubkey_authentication &&
1163
			if (options.pubkey_authentication &&
1158
			    (!pubkey_auth_attempt || allowed != 1))
1164
			    (!pubkey_auth_attempt || allowed != 1))
1159
				auth_clear_options();
1165
				auth_clear_options();
1160
			break;
1166
			break;
1161
		case MM_HOSTKEY:
1167
		case MM_HOSTKEY:
1162
			allowed = options.hostbased_authentication &&
1168
			allowed = options.hostbased_authentication &&
1169
			    !auth2_key_already_used(authctxt, key) &&
1163
			    match_pattern_list(sshkey_ssh_name(key),
1170
			    match_pattern_list(sshkey_ssh_name(key),
1164
			    options.hostbased_key_types, 0) == 1 &&
1171
			    options.hostbased_key_types, 0) == 1 &&
1165
			    hostbased_key_allowed(authctxt->pw,
1172
			    hostbased_key_allowed(authctxt->pw,
1166
			    cuser, chost, key);
1173
			    cuser, chost, key);
1167
			pubkey_auth_info(authctxt, key,
1174
			auth2_record_key(authctxt, 0, key);
1175
			auth2_record_info(authctxt,
1168
			    "client user \"%.100s\", client host \"%.100s\"",
1176
			    "client user \"%.100s\", client host \"%.100s\"",
1169
			    cuser, chost);
1177
			    cuser, chost);
1170
			auth_method = "hostbased";
1178
			auth_method = "hostbased";
Lines 1175-1185 mm_answer_keyallowed(int sock, Buffer *m) Link Here
1175
		}
1183
		}
1176
	}
1184
	}
1177
1185
1178
	debug3("%s: key %p is %s",
1186
	debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed");
1179
	    __func__, key, allowed ? "allowed" : "not allowed");
1180
1187
1181
	if (key != NULL)
1188
	sshkey_free(key);
1182
		key_free(key);
1183
1189
1184
	/* clear temporarily storage (used by verify) */
1190
	/* clear temporarily storage (used by verify) */
1185
	monitor_reset_key_state();
1191
	monitor_reset_key_state();
Lines 1353-1362 mm_answer_keyverify(int sock, Buffer *m) Link Here
1353
	switch (key_blobtype) {
1359
	switch (key_blobtype) {
1354
	case MM_USERKEY:
1360
	case MM_USERKEY:
1355
		valid_data = monitor_valid_userblob(data, datalen);
1361
		valid_data = monitor_valid_userblob(data, datalen);
1362
		auth_method = "publickey";
1356
		break;
1363
		break;
1357
	case MM_HOSTKEY:
1364
	case MM_HOSTKEY:
1358
		valid_data = monitor_valid_hostbasedblob(data, datalen,
1365
		valid_data = monitor_valid_hostbasedblob(data, datalen,
1359
		    hostbased_cuser, hostbased_chost);
1366
		    hostbased_cuser, hostbased_chost);
1367
		auth_method = "hostbased";
1360
		break;
1368
		break;
1361
	default:
1369
	default:
1362
		valid_data = 0;
1370
		valid_data = 0;
Lines 1366-1388 mm_answer_keyverify(int sock, Buffer *m) Link Here
1366
		fatal("%s: bad signature data blob", __func__);
1374
		fatal("%s: bad signature data blob", __func__);
1367
1375
1368
	verified = key_verify(key, signature, signaturelen, data, datalen);
1376
	verified = key_verify(key, signature, signaturelen, data, datalen);
1369
	debug3("%s: key %p signature %s",
1377
	debug3("%s: %s %p signature %s", __func__, auth_method, key,
1370
	    __func__, key, (verified == 1) ? "verified" : "unverified");
1378
	    (verified == 1) ? "verified" : "unverified");
1371
1379
	auth2_record_key(authctxt, verified == 1, key);
1372
	/* If auth was successful then record key to ensure it isn't reused */
1373
	if (verified == 1 && key_blobtype == MM_USERKEY)
1374
		auth2_record_userkey(authctxt, key);
1375
	else
1376
		key_free(key);
1377
1380
1378
	free(blob);
1381
	free(blob);
1379
	free(signature);
1382
	free(signature);
1380
	free(data);
1383
	free(data);
1381
1384
1382
	auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
1383
1384
	monitor_reset_key_state();
1385
	monitor_reset_key_state();
1385
1386
1387
	sshkey_free(key);
1386
	buffer_clear(m);
1388
	buffer_clear(m);
1387
	buffer_put_int(m, verified);
1389
	buffer_put_int(m, verified);
1388
	mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
1390
	mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
Lines 1774-1779 int Link Here
1774
mm_answer_gss_userok(int sock, Buffer *m)
1776
mm_answer_gss_userok(int sock, Buffer *m)
1775
{
1777
{
1776
	int authenticated;
1778
	int authenticated;
1779
	const char *displayname;
1777
1780
1778
	if (!options.gss_authentication)
1781
	if (!options.gss_authentication)
1779
		fatal("%s: GSSAPI authentication not enabled", __func__);
1782
		fatal("%s: GSSAPI authentication not enabled", __func__);
Lines 1788-1793 mm_answer_gss_userok(int sock, Buffer *m) Link Here
1788
1791
1789
	auth_method = "gssapi-with-mic";
1792
	auth_method = "gssapi-with-mic";
1790
1793
1794
	if ((displayname = ssh_gssapi_displayname()) != NULL)
1795
		auth2_record_info(authctxt, "%s", displayname);
1796
1791
	/* Monitor loop will terminate if authenticated */
1797
	/* Monitor loop will terminate if authenticated */
1792
	return (authenticated);
1798
	return (authenticated);
1793
}
1799
}
(-)a/session.c (-22 / +50 lines)
Lines 161-166 login_cap_t *lc; Link Here
161
static int is_child = 0;
161
static int is_child = 0;
162
static int in_chroot = 0;
162
static int in_chroot = 0;
163
163
164
static const char *auth_info = NULL;
165
164
/* Name and directory of socket for authentication agent forwarding. */
166
/* Name and directory of socket for authentication agent forwarding. */
165
static char *auth_sock_name = NULL;
167
static char *auth_sock_name = NULL;
166
static char *auth_sock_dir = NULL;
168
static char *auth_sock_dir = NULL;
Lines 265-271 do_authenticated(Authctxt *authctxt) Link Here
265
267
266
	auth_debug_send();
268
	auth_debug_send();
267
269
270
	auth_info = sshbuf_dup_string(authctxt->session_info);
268
	do_authenticated2(authctxt);
271
	do_authenticated2(authctxt);
272
269
	do_cleanup(authctxt);
273
	do_cleanup(authctxt);
270
}
274
}
271
275
Lines 951-958 read_etc_default_login(char ***env, u_int *envsize, uid_t uid) Link Here
951
}
955
}
952
#endif /* HAVE_ETC_DEFAULT_LOGIN */
956
#endif /* HAVE_ETC_DEFAULT_LOGIN */
953
957
954
void
958
static void
955
copy_environment(char **source, char ***env, u_int *envsize)
959
copy_environment_filtered(char **source, char ***env, u_int *envsize,
960
    const char *blacklist, const char *whitelist)
956
{
961
{
957
	char *var_name, *var_val;
962
	char *var_name, *var_val;
958
	int i;
963
	int i;
Lines 968-980 copy_environment(char **source, char ***env, u_int *envsize) Link Here
968
		}
973
		}
969
		*var_val++ = '\0';
974
		*var_val++ = '\0';
970
975
971
		debug3("Copy environment: %s=%s", var_name, var_val);
976
		/* Apply any filters specified */
972
		child_set_env(env, envsize, var_name, var_val);
977
		if (blacklist != NULL &&
978
		    match_pattern_list(var_name, blacklist, 0) == 1) {
979
			debug3("%s: skipped %s, on blacklist",
980
			    __func__, var_name);
981
		} else if (whitelist != NULL &&
982
		    match_pattern_list(var_name, whitelist, 0) != 1) {
983
			debug3("%s: skipped %s, not on whitelist",
984
			    __func__, var_name);
985
		} else {
986
			debug3("Copy environment: %s=%s", var_name, var_val);
987
			child_set_env(env, envsize, var_name, var_val);
988
		}
973
989
974
		free(var_name);
990
		free(var_name);
975
	}
991
	}
976
}
992
}
977
993
994
void
995
copy_environment(char **source, char ***env, u_int *envsize)
996
{
997
	copy_environment_filtered(source, env, envsize, NULL, NULL);
998
}
999
978
static char **
1000
static char **
979
do_setup_env(Session *s, const char *shell)
1001
do_setup_env(Session *s, const char *shell)
980
{
1002
{
Lines 1001-1006 do_setup_env(Session *s, const char *shell) Link Here
1001
		char **p;
1023
		char **p;
1002
1024
1003
		p = fetch_windows_environment();
1025
		p = fetch_windows_environment();
1026
		/* XXX use whitelist */
1004
		copy_environment(p, &env, &envsize);
1027
		copy_environment(p, &env, &envsize);
1005
		free_windows_environment(p);
1028
		free_windows_environment(p);
1006
	}
1029
	}
Lines 1056-1061 do_setup_env(Session *s, const char *shell) Link Here
1056
	if (getenv("TZ"))
1079
	if (getenv("TZ"))
1057
		child_set_env(&env, &envsize, "TZ", getenv("TZ"));
1080
		child_set_env(&env, &envsize, "TZ", getenv("TZ"));
1058
1081
1082
#ifdef USE_PAM
1083
	/*
1084
	 * Pull in any environment variables that may have
1085
	 * been set by PAM.
1086
	 */
1087
	if (options.use_pam) {
1088
		char **p;
1089
1090
		/* Don't allow SSH_USER_AUTH to leak back from PAM */
1091
		p = fetch_pam_child_environment();
1092
		copy_environment_filtered(p, &env, &envsize,
1093
		    "SSH_USER_AUTH", NULL);
1094
		free_pam_environment(p);
1095
1096
		p = fetch_pam_environment();
1097
		copy_environment_filtered(p, &env, &envsize,
1098
		    "SSH_USER_AUTH", NULL);
1099
		free_pam_environment(p);
1100
	}
1101
#endif /* USE_PAM */
1102
1059
	/* Set custom environment options from RSA authentication. */
1103
	/* Set custom environment options from RSA authentication. */
1060
	while (custom_environment) {
1104
	while (custom_environment) {
1061
		struct envstring *ce = custom_environment;
1105
		struct envstring *ce = custom_environment;
Lines 1085-1090 do_setup_env(Session *s, const char *shell) Link Here
1085
	free(laddr);
1129
	free(laddr);
1086
	child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
1130
	child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
1087
1131
1132
	if (auth_info)
1133
		child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info);
1088
	if (s->ttyfd != -1)
1134
	if (s->ttyfd != -1)
1089
		child_set_env(&env, &envsize, "SSH_TTY", s->tty);
1135
		child_set_env(&env, &envsize, "SSH_TTY", s->tty);
1090
	if (s->term)
1136
	if (s->term)
Lines 1094-1100 do_setup_env(Session *s, const char *shell) Link Here
1094
	if (original_command)
1140
	if (original_command)
1095
		child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
1141
		child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
1096
		    original_command);
1142
		    original_command);
1097
1098
#ifdef _UNICOS
1143
#ifdef _UNICOS
1099
	if (cray_tmpdir[0] != '\0')
1144
	if (cray_tmpdir[0] != '\0')
1100
		child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
1145
		child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
Lines 1126-1148 do_setup_env(Session *s, const char *shell) Link Here
1126
		child_set_env(&env, &envsize, "KRB5CCNAME",
1171
		child_set_env(&env, &envsize, "KRB5CCNAME",
1127
		    s->authctxt->krb5_ccname);
1172
		    s->authctxt->krb5_ccname);
1128
#endif
1173
#endif
1129
#ifdef USE_PAM
1130
	/*
1131
	 * Pull in any environment variables that may have
1132
	 * been set by PAM.
1133
	 */
1134
	if (options.use_pam) {
1135
		char **p;
1136
1137
		p = fetch_pam_child_environment();
1138
		copy_environment(p, &env, &envsize);
1139
		free_pam_environment(p);
1140
1141
		p = fetch_pam_environment();
1142
		copy_environment(p, &env, &envsize);
1143
		free_pam_environment(p);
1144
	}
1145
#endif /* USE_PAM */
1146
1174
1147
	if (auth_sock_name != NULL)
1175
	if (auth_sock_name != NULL)
1148
		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
1176
		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
(-)a/ssh-gss.h (+1 lines)
Lines 128-133 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); Link Here
128
void ssh_gssapi_do_child(char ***, u_int *);
128
void ssh_gssapi_do_child(char ***, u_int *);
129
void ssh_gssapi_cleanup_creds(void);
129
void ssh_gssapi_cleanup_creds(void);
130
void ssh_gssapi_storecreds(void);
130
void ssh_gssapi_storecreds(void);
131
const char *ssh_gssapi_displayname(void);
131
132
132
#endif /* GSSAPI */
133
#endif /* GSSAPI */
133
134
(-)a/sshkey.c (-1 / +1 lines)
Lines 1331-1337 sshkey_to_base64(const struct sshkey *key, char **b64p) Link Here
1331
	return r;
1331
	return r;
1332
}
1332
}
1333
1333
1334
static int
1334
int
1335
sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
1335
sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
1336
{
1336
{
1337
	int r = SSH_ERR_INTERNAL_ERROR;
1337
	int r = SSH_ERR_INTERNAL_ERROR;
(-)a/sshkey.h (+1 lines)
Lines 124-129 int sshkey_fingerprint_raw(const struct sshkey *k, Link Here
124
    int, u_char **retp, size_t *lenp);
124
    int, u_char **retp, size_t *lenp);
125
const char	*sshkey_type(const struct sshkey *);
125
const char	*sshkey_type(const struct sshkey *);
126
const char	*sshkey_cert_type(const struct sshkey *);
126
const char	*sshkey_cert_type(const struct sshkey *);
127
int		 sshkey_format_text(const struct sshkey *, struct sshbuf *);
127
int		 sshkey_write(const struct sshkey *, FILE *);
128
int		 sshkey_write(const struct sshkey *, FILE *);
128
int		 sshkey_read(struct sshkey *, char **);
129
int		 sshkey_read(struct sshkey *, char **);
129
u_int		 sshkey_size(const struct sshkey *);
130
u_int		 sshkey_size(const struct sshkey *);

Return to bug 2408