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

Collapse All | Expand All

(-)a/auth-pam.c (+4 lines)
Lines 688-693 sshpam_init_ctx(Authctxt *authctxt) Link Here
688
		return (NULL);
688
		return (NULL);
689
	}
689
	}
690
690
691
	/* Notify PAM about any already successful auth methods */
692
	if (authctxt->auth_details)
693
		do_pam_putenv("SSH_USER_AUTH", authctxt->auth_details);
694
691
	ctxt = xcalloc(1, sizeof *ctxt);
695
	ctxt = xcalloc(1, sizeof *ctxt);
692
696
693
	/* Start the authentication thread */
697
	/* Start the authentication thread */
(-)a/auth.h (+4 lines)
Lines 81-86 struct Authctxt { Link Here
81
81
82
	struct sshkey	**prev_userkeys;
82
	struct sshkey	**prev_userkeys;
83
	u_int		 nprev_userkeys;
83
	u_int		 nprev_userkeys;
84
85
	char		*last_details;
86
	char		*auth_details;
84
};
87
};
85
/*
88
/*
86
 * Every authentication method has to handle authentication requests for
89
 * Every authentication method has to handle authentication requests for
Lines 127-132 int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); Link Here
127
int	 auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
130
int	 auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
128
int	 hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
131
int	 hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
129
int	 user_key_allowed(struct passwd *, Key *, int);
132
int	 user_key_allowed(struct passwd *, Key *, int);
133
char	*pubkey_format(const Key *key);
130
void	 pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
134
void	 pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
131
	    __attribute__((__format__ (printf, 3, 4)));
135
	    __attribute__((__format__ (printf, 3, 4)));
132
void	 auth2_record_userkey(Authctxt *, struct sshkey *);
136
void	 auth2_record_userkey(Authctxt *, struct sshkey *);
(-)a/auth2-hostbased.c (-4 / +10 lines)
Lines 60-66 userauth_hostbased(Authctxt *authctxt) Link Here
60
{
60
{
61
	Buffer b;
61
	Buffer b;
62
	Key *key = NULL;
62
	Key *key = NULL;
63
	char *pkalg, *cuser, *chost, *service;
63
	char *pkalg, *cuser, *chost, *service, *pubkey;
64
	u_char *pkblob, *sig;
64
	u_char *pkblob, *sig;
65
	u_int alen, blen, slen;
65
	u_int alen, blen, slen;
66
	int pktype;
66
	int pktype;
Lines 132-146 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
	pubkey = pubkey_format(key);
136
	    "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
136
	auth_info(authctxt,
137
	    "%s, client user \"%.100s\", client host \"%.100s\"",
138
	    pubkey, cuser, chost);
137
139
138
	/* test for allowed key and correct signature */
140
	/* test for allowed key and correct signature */
139
	authenticated = 0;
141
	authenticated = 0;
140
	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
142
	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
141
	    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
143
	    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
142
			buffer_len(&b))) == 1)
144
			buffer_len(&b))) == 1) {
143
		authenticated = 1;
145
		authenticated = 1;
146
		authctxt->last_details = pubkey;
147
	} else {
148
		free(pubkey);
149
	}
144
150
145
	buffer_free(&b);
151
	buffer_free(&b);
146
done:
152
done:
(-)a/auth2-pubkey.c (-22 / +36 lines)
Lines 79-85 userauth_pubkey(Authctxt *authctxt) Link Here
79
{
79
{
80
	Buffer b;
80
	Buffer b;
81
	Key *key = NULL;
81
	Key *key = NULL;
82
	char *pkalg, *userstyle;
82
	char *pkalg, *userstyle, *pubkey;
83
	u_char *pkblob, *sig;
83
	u_char *pkblob, *sig;
84
	u_int alen, blen, slen;
84
	u_int alen, blen, slen;
85
	int have_sig, pktype;
85
	int have_sig, pktype;
Lines 168-174 userauth_pubkey(Authctxt *authctxt) Link Here
168
#ifdef DEBUG_PK
168
#ifdef DEBUG_PK
169
		buffer_dump(&b);
169
		buffer_dump(&b);
170
#endif
170
#endif
171
		pubkey_auth_info(authctxt, key, NULL);
171
		pubkey = pubkey_format(key);
172
		auth_info(authctxt, "%s", pubkey);
172
173
173
		/* test for correct signature */
174
		/* test for correct signature */
174
		authenticated = 0;
175
		authenticated = 0;
Lines 176-184 userauth_pubkey(Authctxt *authctxt) Link Here
176
		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
177
		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
177
		    buffer_len(&b))) == 1) {
178
		    buffer_len(&b))) == 1) {
178
			authenticated = 1;
179
			authenticated = 1;
180
			authctxt->last_details = pubkey;
179
			/* Record the successful key to prevent reuse */
181
			/* Record the successful key to prevent reuse */
180
			auth2_record_userkey(authctxt, key);
182
			auth2_record_userkey(authctxt, key);
181
			key = NULL; /* Don't free below */
183
			key = NULL; /* Don't free below */
184
		} else {
185
			free(pubkey);
182
		}
186
		}
183
		buffer_free(&b);
187
		buffer_free(&b);
184
		free(sig);
188
		free(sig);
Lines 214-253 done: Link Here
214
	return authenticated;
218
	return authenticated;
215
}
219
}
216
220
217
void
221
char *
218
pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
222
pubkey_format(const Key *key)
219
{
223
{
220
	char *fp, *extra;
224
	char *fp, *result;
221
	va_list ap;
222
	int i;
223
224
	extra = NULL;
225
	if (fmt != NULL) {
226
		va_start(ap, fmt);
227
		i = vasprintf(&extra, fmt, ap);
228
		va_end(ap);
229
		if (i < 0 || extra == NULL)
230
			fatal("%s: vasprintf failed", __func__);	
231
	}
232
225
233
	if (key_is_cert(key)) {
226
	if (key_is_cert(key)) {
234
		fp = sshkey_fingerprint(key->cert->signature_key,
227
		fp = sshkey_fingerprint(key->cert->signature_key,
235
		    options.fingerprint_hash, SSH_FP_DEFAULT);
228
		    options.fingerprint_hash, SSH_FP_DEFAULT);
236
		auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 
229
		xasprintf(&result, "%s ID %s (serial %llu) CA %s %s",
237
		    key_type(key), key->cert->key_id,
230
		    key_type(key), key->cert->key_id,
238
		    (unsigned long long)key->cert->serial,
231
		    (unsigned long long)key->cert->serial,
239
		    key_type(key->cert->signature_key),
232
		    key_type(key->cert->signature_key),
240
		    fp == NULL ? "(null)" : fp,
233
		    fp == NULL ? "(null)" : fp);
241
		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
242
		free(fp);
234
		free(fp);
243
	} else {
235
	} else {
244
		fp = sshkey_fingerprint(key, options.fingerprint_hash,
236
		fp = sshkey_fingerprint(key, options.fingerprint_hash,
245
		    SSH_FP_DEFAULT);
237
		    SSH_FP_DEFAULT);
246
		auth_info(authctxt, "%s %s%s%s", key_type(key),
238
		xasprintf(&result, "%s %s", key_type(key),
247
		    fp == NULL ? "(null)" : fp,
239
		    fp == NULL ? "(null)" : fp);
248
		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
249
		free(fp);
240
		free(fp);
250
	}
241
	}
242
243
	return result;
244
}
245
246
void
247
pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
248
{
249
	char *extra, *pubkey;
250
	va_list ap;
251
	int i;
252
253
	extra = NULL;
254
	if (fmt != NULL) {
255
		va_start(ap, fmt);
256
		i = vasprintf(&extra, fmt, ap);
257
		va_end(ap);
258
		if (i < 0 || extra == NULL)
259
			fatal("%s: vasprintf failed", __func__);
260
	}
261
262
	pubkey = pubkey_format(key);
263
	auth_info(authctxt, "%s%s%s", pubkey, extra == NULL ? "" : ", ",
264
	    extra == NULL ? "" : extra);
251
	free(extra);
265
	free(extra);
252
}
266
}
253
267
(-)a/auth2.c (+13 lines)
Lines 293-298 userauth_finish(Authctxt *authctxt, int authenticated, const char *method, Link Here
293
    const char *submethod)
293
    const char *submethod)
294
{
294
{
295
	char *methods;
295
	char *methods;
296
	char *prev_auth_details;
296
	int partial = 0;
297
	int partial = 0;
297
298
298
	if (!authctxt->valid && authenticated)
299
	if (!authctxt->valid && authenticated)
Lines 323-328 userauth_finish(Authctxt *authctxt, int authenticated, const char *method, Link Here
323
	if (authctxt->postponed)
324
	if (authctxt->postponed)
324
		return;
325
		return;
325
326
327
	if (authenticated || partial) {
328
		prev_auth_details = authctxt->auth_details;
329
		xasprintf(&authctxt->auth_details, "%s%s%s%s%s",
330
		    prev_auth_details ? prev_auth_details : "",
331
		    prev_auth_details ? ", " : "", method,
332
		    authctxt->last_details ? ": " : "",
333
		    authctxt->last_details ? authctxt->last_details : "");
334
		free(authctxt->last_details);
335
		authctxt->last_details = NULL;
336
		free(prev_auth_details);
337
	}
338
326
#ifdef USE_PAM
339
#ifdef USE_PAM
327
	if (options.use_pam && authenticated) {
340
	if (options.use_pam && authenticated) {
328
		if (!PRIVSEP(do_pam_account())) {
341
		if (!PRIVSEP(do_pam_account())) {
(-)a/monitor.c (+9 lines)
Lines 335-340 monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) Link Here
335
{
335
{
336
	struct mon_table *ent;
336
	struct mon_table *ent;
337
	int authenticated = 0, partial = 0;
337
	int authenticated = 0, partial = 0;
338
	char *prev_auth_details;
338
339
339
	debug3("preauth child monitor started");
340
	debug3("preauth child monitor started");
340
341
Lines 366-371 monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) Link Here
366
		auth_submethod = NULL;
367
		auth_submethod = NULL;
367
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
368
		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
368
369
370
		if (authenticated) {
371
			prev_auth_details = authctxt->auth_details;
372
			xasprintf(&authctxt->auth_details, "%s%s%s",
373
			    prev_auth_details ? prev_auth_details : "",
374
			    prev_auth_details ? ", " : "", auth_method);
375
			free(prev_auth_details);
376
		}
377
369
		/* Special handling for multiple required authentications */
378
		/* Special handling for multiple required authentications */
370
		if (options.num_auth_methods != 0) {
379
		if (options.num_auth_methods != 0) {
371
			if (!compat20)
380
			if (!compat20)
(-)a/session.c (+7 lines)
Lines 1307-1312 do_setup_env(Session *s, const char *shell) Link Here
1307
	}
1307
	}
1308
#endif /* USE_PAM */
1308
#endif /* USE_PAM */
1309
1309
1310
	if (s->authctxt->auth_details)
1311
		child_set_env(&env, &envsize, "SSH_USER_AUTH",
1312
		     s->authctxt->auth_details);
1313
1310
	if (auth_sock_name != NULL)
1314
	if (auth_sock_name != NULL)
1311
		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
1315
		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
1312
		    auth_sock_name);
1316
		    auth_sock_name);
Lines 2735-2740 do_cleanup(Authctxt *authctxt) Link Here
2735
	if (authctxt == NULL)
2739
	if (authctxt == NULL)
2736
		return;
2740
		return;
2737
2741
2742
	free(authctxt->auth_details);
2743
	authctxt->auth_details = NULL;
2744
2738
#ifdef USE_PAM
2745
#ifdef USE_PAM
2739
	if (options.use_pam) {
2746
	if (options.use_pam) {
2740
		sshpam_cleanup();
2747
		sshpam_cleanup();
(-)a/ssh.1 (+4 lines)
Lines 1402-1407 server IP address, and server port number. Link Here
1402
This variable contains the original command line if a forced command
1402
This variable contains the original command line if a forced command
1403
is executed.
1403
is executed.
1404
It can be used to extract the original arguments.
1404
It can be used to extract the original arguments.
1405
.It Ev SSH_USER_AUTH
1406
This variable contains, for SSH2 only, a comma-separated list of authentication
1407
methods that were successfuly used to authenticate. When possible, these
1408
methods are extended with detailed information on the credential used.
1405
.It Ev SSH_TTY
1409
.It Ev SSH_TTY
1406
This is set to the name of the tty (path to the device) associated
1410
This is set to the name of the tty (path to the device) associated
1407
with the current shell or command.
1411
with the current shell or command.

Return to bug 2408