summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auth.c62
-rw-r--r--auth.h48
-rw-r--r--auth2-gss.c12
-rw-r--r--auth2-hostbased.c8
-rw-r--r--auth2-pubkey.c80
-rw-r--r--auth2.c133
-rw-r--r--gss-serv.c11
-rw-r--r--monitor.c41
-rw-r--r--servconf.c13
-rw-r--r--servconf.h3
-rw-r--r--session.c54
-rw-r--r--ssh-gss.h3
-rw-r--r--sshd_config.510
13 files changed, 338 insertions, 140 deletions
diff --git a/auth.c b/auth.c
index fd8211505..96116ecfe 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.c,v 1.121 2017/05/30 08:52:19 markus Exp $ */ 1/* $OpenBSD: auth.c,v 1.122 2017/06/24 06:34:38 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -267,21 +267,41 @@ allowed_user(struct passwd * pw)
267 return 1; 267 return 1;
268} 268}
269 269
270void 270/*
271auth_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 */
274static char *
275format_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
287void 307void
@@ -290,7 +310,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
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;
@@ -309,6 +330,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
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,
@@ -317,10 +343,10 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
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); 348
323 authctxt->info = NULL; 349 free(extra);
324 350
325#ifdef CUSTOM_FAILED_LOGIN 351#ifdef CUSTOM_FAILED_LOGIN
326 if (authenticated == 0 && !authctxt->postponed && 352 if (authenticated == 0 && !authctxt->postponed &&
diff --git a/auth.h b/auth.h
index 677935463..cbbc9623f 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.91 2017/05/30 14:29:59 markus Exp $ */ 1/* $OpenBSD: auth.h,v 1.92 2017/06/24 06:34:38 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -44,6 +44,7 @@
44 44
45struct ssh; 45struct ssh;
46struct sshkey; 46struct sshkey;
47struct sshbuf;
47 48
48typedef struct Authctxt Authctxt; 49typedef struct Authctxt Authctxt;
49typedef struct Authmethod Authmethod; 50typedef struct Authmethod Authmethod;
@@ -62,13 +63,17 @@ struct Authctxt {
62 char *service; 63 char *service;
63 struct passwd *pw; /* set if 'valid' */ 64 struct passwd *pw; /* set if 'valid' */
64 char *style; 65 char *style;
66
67 /* Method lists for multiple authentication */
68 char **auth_methods; /* modified from server config */
69 u_int num_auth_methods;
70
71 /* Authentication method-specific data */
72 void *methoddata;
65 void *kbdintctxt; 73 void *kbdintctxt;
66 char *info; /* Extra info for next auth_log */
67#ifdef BSD_AUTH 74#ifdef BSD_AUTH
68 auth_session_t *as; 75 auth_session_t *as;
69#endif 76#endif
70 char **auth_methods; /* modified from server config */
71 u_int num_auth_methods;
72#ifdef KRB5 77#ifdef KRB5
73 krb5_context krb5_ctx; 78 krb5_context krb5_ctx;
74 krb5_ccache krb5_fwd_ccache; 79 krb5_ccache krb5_fwd_ccache;
@@ -76,12 +81,20 @@ struct Authctxt {
76 char *krb5_ticket_file; 81 char *krb5_ticket_file;
77 char *krb5_ccname; 82 char *krb5_ccname;
78#endif 83#endif
79 Buffer *loginmsg; 84 struct sshbuf *loginmsg;
80 void *methoddata; 85
86 /* Authentication keys already used; these will be refused henceforth */
87 struct sshkey **prev_keys;
88 u_int nprev_keys;
81 89
82 struct sshkey **prev_userkeys; 90 /* Last used key and ancilliary information from active auth method */
83 u_int nprev_userkeys; 91 struct sshkey *auth_method_key;
92 char *auth_method_info;
93
94 /* Information exposed to session */
95 struct sshbuf *session_info; /* Auth info for environment */
84}; 96};
97
85/* 98/*
86 * Every authentication method has to handle authentication requests for 99 * Every authentication method has to handle authentication requests for
87 * non-existing users, or for users that are not allowed to login. In this 100 * non-existing users, or for users that are not allowed to login. In this
@@ -120,10 +133,18 @@ int auth_password(Authctxt *, const char *);
120int hostbased_key_allowed(struct passwd *, const char *, char *, 133int hostbased_key_allowed(struct passwd *, const char *, char *,
121 struct sshkey *); 134 struct sshkey *);
122int user_key_allowed(struct passwd *, struct sshkey *, int); 135int user_key_allowed(struct passwd *, struct sshkey *, int);
123void pubkey_auth_info(Authctxt *, const struct sshkey *, const char *, ...) 136int auth2_key_already_used(Authctxt *, const struct sshkey *);
124 __attribute__((__format__ (printf, 3, 4))); 137
125void auth2_record_userkey(Authctxt *, struct sshkey *); 138/*
126int auth2_userkey_already_used(Authctxt *, struct sshkey *); 139 * Handling auth method-specific information for logging and prevention
140 * of key reuse during multiple authentication.
141 */
142void auth2_authctxt_reset_info(Authctxt *);
143void auth2_record_key(Authctxt *, int, const struct sshkey *);
144void auth2_record_info(Authctxt *authctxt, const char *, ...)
145 __attribute__((__format__ (printf, 2, 3)))
146 __attribute__((__nonnull__ (2)));
147void auth2_update_session_info(Authctxt *, const char *, const char *);
127 148
128struct stat; 149struct stat;
129int auth_secure_path(const char *, struct stat *, const char *, uid_t, 150int auth_secure_path(const char *, struct stat *, const char *, uid_t,
@@ -150,9 +171,6 @@ void disable_forwarding(void);
150 171
151void do_authentication2(Authctxt *); 172void do_authentication2(Authctxt *);
152 173
153void auth_info(Authctxt *authctxt, const char *, ...)
154 __attribute__((__format__ (printf, 2, 3)))
155 __attribute__((__nonnull__ (2)));
156void auth_log(Authctxt *, int, int, const char *, const char *); 174void auth_log(Authctxt *, int, int, const char *, const char *);
157void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn)); 175void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
158void userauth_finish(struct ssh *, int, const char *, const char *); 176void userauth_finish(struct ssh *, int, const char *, const char *);
diff --git a/auth2-gss.c b/auth2-gss.c
index 680d5e712..589283b72 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-gss.c,v 1.25 2017/05/30 14:29:59 markus Exp $ */ 1/* $OpenBSD: auth2-gss.c,v 1.26 2017/06/24 06:34:38 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. 4 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -228,6 +228,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
228{ 228{
229 Authctxt *authctxt = ssh->authctxt; 229 Authctxt *authctxt = ssh->authctxt;
230 int authenticated; 230 int authenticated;
231 const char *displayname;
231 232
232 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 233 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
233 fatal("No authentication or GSSAPI context"); 234 fatal("No authentication or GSSAPI context");
@@ -241,6 +242,10 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
241 242
242 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 243 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
243 244
245 if ((!use_privsep || mm_is_monitor()) &&
246 (displayname = ssh_gssapi_displayname()) != NULL)
247 auth2_record_info(authctxt, "%s", displayname);
248
244 authctxt->postponed = 0; 249 authctxt->postponed = 0;
245 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 250 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
246 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); 251 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
@@ -259,6 +264,7 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
259 Buffer b; 264 Buffer b;
260 gss_buffer_desc mic, gssbuf; 265 gss_buffer_desc mic, gssbuf;
261 u_int len; 266 u_int len;
267 const char *displayname;
262 268
263 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 269 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
264 fatal("No authentication or GSSAPI context"); 270 fatal("No authentication or GSSAPI context");
@@ -282,6 +288,10 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
282 buffer_free(&b); 288 buffer_free(&b);
283 free(mic.value); 289 free(mic.value);
284 290
291 if ((!use_privsep || mm_is_monitor()) &&
292 (displayname = ssh_gssapi_displayname()) != NULL)
293 auth2_record_info(authctxt, "%s", displayname);
294
285 authctxt->postponed = 0; 295 authctxt->postponed = 0;
286 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 296 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
287 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); 297 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 63fe9ae65..92758b38c 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-hostbased.c,v 1.30 2017/05/30 14:29:59 markus Exp $ */ 1/* $OpenBSD: auth2-hostbased.c,v 1.31 2017/06/24 06:34:38 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -137,7 +137,7 @@ userauth_hostbased(struct ssh *ssh)
137 sshbuf_dump(b, stderr); 137 sshbuf_dump(b, stderr);
138#endif 138#endif
139 139
140 pubkey_auth_info(authctxt, key, 140 auth2_record_info(authctxt,
141 "client user \"%.100s\", client host \"%.100s\"", cuser, chost); 141 "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
142 142
143 /* test for allowed key and correct signature */ 143 /* test for allowed key and correct signature */
@@ -147,11 +147,11 @@ userauth_hostbased(struct ssh *ssh)
147 sshbuf_ptr(b), sshbuf_len(b), ssh->compat)) == 0) 147 sshbuf_ptr(b), sshbuf_len(b), ssh->compat)) == 0)
148 authenticated = 1; 148 authenticated = 1;
149 149
150 auth2_record_key(authctxt, authenticated, key);
150 sshbuf_free(b); 151 sshbuf_free(b);
151done: 152done:
152 debug2("%s: authenticated %d", __func__, authenticated); 153 debug2("%s: authenticated %d", __func__, authenticated);
153 if (key != NULL) 154 sshkey_free(key);
154 sshkey_free(key);
155 free(pkalg); 155 free(pkalg);
156 free(pkblob); 156 free(pkblob);
157 free(cuser); 157 free(cuser);
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 5794f1f4d..1c59b5bb0 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.67 2017/05/31 10:54:00 markus Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.68 2017/06/24 06:34:38 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -137,7 +137,7 @@ userauth_pubkey(struct ssh *ssh)
137 goto done; 137 goto done;
138 } 138 }
139 fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); 139 fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
140 if (auth2_userkey_already_used(authctxt, key)) { 140 if (auth2_key_already_used(authctxt, key)) {
141 logit("refusing previously-used %s key", sshkey_type(key)); 141 logit("refusing previously-used %s key", sshkey_type(key));
142 goto done; 142 goto done;
143 } 143 }
@@ -194,7 +194,6 @@ userauth_pubkey(struct ssh *ssh)
194#ifdef DEBUG_PK 194#ifdef DEBUG_PK
195 sshbuf_dump(b, stderr); 195 sshbuf_dump(b, stderr);
196#endif 196#endif
197 pubkey_auth_info(authctxt, key, NULL);
198 197
199 /* test for correct signature */ 198 /* test for correct signature */
200 authenticated = 0; 199 authenticated = 0;
@@ -202,12 +201,10 @@ userauth_pubkey(struct ssh *ssh)
202 PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b), 201 PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
203 sshbuf_len(b), ssh->compat)) == 0) { 202 sshbuf_len(b), ssh->compat)) == 0) {
204 authenticated = 1; 203 authenticated = 1;
205 /* Record the successful key to prevent reuse */
206 auth2_record_userkey(authctxt, key);
207 key = NULL; /* Don't free below */
208 } 204 }
209 sshbuf_free(b); 205 sshbuf_free(b);
210 free(sig); 206 free(sig);
207 auth2_record_key(authctxt, authenticated, key);
211 } else { 208 } else {
212 debug("%s: test whether pkalg/pkblob are acceptable for %s %s", 209 debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
213 __func__, sshkey_type(key), fp); 210 __func__, sshkey_type(key), fp);
@@ -237,8 +234,7 @@ userauth_pubkey(struct ssh *ssh)
237 auth_clear_options(); 234 auth_clear_options();
238done: 235done:
239 debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg); 236 debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
240 if (key != NULL) 237 sshkey_free(key);
241 sshkey_free(key);
242 free(userstyle); 238 free(userstyle);
243 free(pkalg); 239 free(pkalg);
244 free(pkblob); 240 free(pkblob);
@@ -246,44 +242,6 @@ done:
246 return authenticated; 242 return authenticated;
247} 243}
248 244
249void
250pubkey_auth_info(Authctxt *authctxt, const struct sshkey *key,
251 const char *fmt, ...)
252{
253 char *fp, *extra;
254 va_list ap;
255 int i;
256
257 extra = NULL;
258 if (fmt != NULL) {
259 va_start(ap, fmt);
260 i = vasprintf(&extra, fmt, ap);
261 va_end(ap);
262 if (i < 0 || extra == NULL)
263 fatal("%s: vasprintf failed", __func__);
264 }
265
266 if (sshkey_is_cert(key)) {
267 fp = sshkey_fingerprint(key->cert->signature_key,
268 options.fingerprint_hash, SSH_FP_DEFAULT);
269 auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
270 sshkey_type(key), key->cert->key_id,
271 (unsigned long long)key->cert->serial,
272 sshkey_type(key->cert->signature_key),
273 fp == NULL ? "(null)" : fp,
274 extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
275 free(fp);
276 } else {
277 fp = sshkey_fingerprint(key, options.fingerprint_hash,
278 SSH_FP_DEFAULT);
279 auth_info(authctxt, "%s %s%s%s", sshkey_type(key),
280 fp == NULL ? "(null)" : fp,
281 extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
282 free(fp);
283 }
284 free(extra);
285}
286
287/* 245/*
288 * Splits 's' into an argument vector. Handles quoted string and basic 246 * Splits 's' into an argument vector. Handles quoted string and basic
289 * escape characters (\\, \", \'). Caller must free the argument vector 247 * escape characters (\\, \", \'). Caller must free the argument vector
@@ -1148,36 +1106,6 @@ user_key_allowed(struct passwd *pw, struct sshkey *key, int auth_attempt)
1148 return success; 1106 return success;
1149} 1107}
1150 1108
1151/* Records a public key in the list of previously-successful keys */
1152void
1153auth2_record_userkey(Authctxt *authctxt, struct sshkey *key)
1154{
1155 struct sshkey **tmp;
1156
1157 if (authctxt->nprev_userkeys >= INT_MAX ||
1158 (tmp = recallocarray(authctxt->prev_userkeys,
1159 authctxt->nprev_userkeys, authctxt->nprev_userkeys + 1,
1160 sizeof(*tmp))) == NULL)
1161 fatal("%s: recallocarray failed", __func__);
1162 authctxt->prev_userkeys = tmp;
1163 authctxt->prev_userkeys[authctxt->nprev_userkeys] = key;
1164 authctxt->nprev_userkeys++;
1165}
1166
1167/* Checks whether a key has already been used successfully for authentication */
1168int
1169auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key)
1170{
1171 u_int i;
1172
1173 for (i = 0; i < authctxt->nprev_userkeys; i++) {
1174 if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) {
1175 return 1;
1176 }
1177 }
1178 return 0;
1179}
1180
1181Authmethod method_pubkey = { 1109Authmethod method_pubkey = {
1182 "publickey", 1110 "publickey",
1183 userauth_pubkey, 1111 userauth_pubkey,
diff --git a/auth2.c b/auth2.c
index cb4c2fd5d..862e09960 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2.c,v 1.142 2017/05/31 07:00:13 markus Exp $ */ 1/* $OpenBSD: auth2.c,v 1.143 2017/06/24 06:34:38 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -30,6 +30,7 @@
30#include <sys/uio.h> 30#include <sys/uio.h>
31 31
32#include <fcntl.h> 32#include <fcntl.h>
33#include <limits.h>
33#include <pwd.h> 34#include <pwd.h>
34#include <stdarg.h> 35#include <stdarg.h>
35#include <string.h> 36#include <string.h>
@@ -55,6 +56,7 @@
55#include "ssh-gss.h" 56#include "ssh-gss.h"
56#endif 57#endif
57#include "monitor_wrap.h" 58#include "monitor_wrap.h"
59#include "ssherr.h"
58 60
59/* import */ 61/* import */
60extern ServerOptions options; 62extern ServerOptions options;
@@ -277,6 +279,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
277 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); 279 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
278#endif 280#endif
279 281
282 auth2_authctxt_reset_info(authctxt);
280 authctxt->postponed = 0; 283 authctxt->postponed = 0;
281 authctxt->server_caused_failure = 0; 284 authctxt->server_caused_failure = 0;
282 285
@@ -327,6 +330,10 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method,
327 /* Log before sending the reply */ 330 /* Log before sending the reply */
328 auth_log(authctxt, authenticated, partial, method, submethod); 331 auth_log(authctxt, authenticated, partial, method, submethod);
329 332
333 /* Update information exposed to session */
334 if (authenticated || partial)
335 auth2_update_session_info(authctxt, method, submethod);
336
330 if (authctxt->postponed) 337 if (authctxt->postponed)
331 return; 338 return;
332 339
@@ -624,4 +631,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
624 return 0; 631 return 0;
625} 632}
626 633
634/* Reset method-specific information */
635void auth2_authctxt_reset_info(Authctxt *authctxt)
636{
637 sshkey_free(authctxt->auth_method_key);
638 free(authctxt->auth_method_info);
639 authctxt->auth_method_key = NULL;
640 authctxt->auth_method_info = NULL;
641}
642
643/* Record auth method-specific information for logs */
644void
645auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
646{
647 va_list ap;
648 int i;
649
650 free(authctxt->auth_method_info);
651 authctxt->auth_method_info = NULL;
652
653 va_start(ap, fmt);
654 i = vasprintf(&authctxt->auth_method_info, fmt, ap);
655 va_end(ap);
656
657 if (i < 0 || authctxt->auth_method_info == NULL)
658 fatal("%s: vasprintf failed", __func__);
659}
660
661/*
662 * Records a public key used in authentication. This is used for logging
663 * and to ensure that the same key is not subsequently accepted again for
664 * multiple authentication.
665 */
666void
667auth2_record_key(Authctxt *authctxt, int authenticated,
668 const struct sshkey *key)
669{
670 struct sshkey **tmp, *dup;
671 int r;
672
673 if ((r = sshkey_demote(key, &dup)) != 0)
674 fatal("%s: copy key: %s", __func__, ssh_err(r));
675 sshkey_free(authctxt->auth_method_key);
676 authctxt->auth_method_key = dup;
677
678 if (!authenticated)
679 return;
680
681 /* If authenticated, make sure we don't accept this key again */
682 if ((r = sshkey_demote(key, &dup)) != 0)
683 fatal("%s: copy key: %s", __func__, ssh_err(r));
684 if (authctxt->nprev_keys >= INT_MAX ||
685 (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
686 authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL)
687 fatal("%s: reallocarray failed", __func__);
688 authctxt->prev_keys = tmp;
689 authctxt->prev_keys[authctxt->nprev_keys] = dup;
690 authctxt->nprev_keys++;
691
692}
693
694/* Checks whether a key has already been previously used for authentication */
695int
696auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
697{
698 u_int i;
699 char *fp;
700
701 for (i = 0; i < authctxt->nprev_keys; i++) {
702 if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
703 fp = sshkey_fingerprint(authctxt->prev_keys[i],
704 options.fingerprint_hash, SSH_FP_DEFAULT);
705 debug3("%s: key already used: %s %s", __func__,
706 sshkey_type(authctxt->prev_keys[i]),
707 fp == NULL ? "UNKNOWN" : fp);
708 free(fp);
709 return 1;
710 }
711 }
712 return 0;
713}
714
715/*
716 * Updates authctxt->session_info with details of authentication. Should be
717 * whenever an authentication method succeeds.
718 */
719void
720auth2_update_session_info(Authctxt *authctxt, const char *method,
721 const char *submethod)
722{
723 int r;
724
725 if (authctxt->session_info == NULL) {
726 if ((authctxt->session_info = sshbuf_new()) == NULL)
727 fatal("%s: sshbuf_new", __func__);
728 }
729
730 /* Append method[/submethod] */
731 if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
732 method, submethod == NULL ? "" : "/",
733 submethod == NULL ? "" : submethod)) != 0)
734 fatal("%s: append method: %s", __func__, ssh_err(r));
735
736 /* Append key if present */
737 if (authctxt->auth_method_key != NULL) {
738 if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
739 (r = sshkey_format_text(authctxt->auth_method_key,
740 authctxt->session_info)) != 0)
741 fatal("%s: append key: %s", __func__, ssh_err(r));
742 }
743
744 if (authctxt->auth_method_info != NULL) {
745 /* Ensure no ambiguity here */
746 if (strchr(authctxt->auth_method_info, '\n') != NULL)
747 fatal("%s: auth_method_info contains \\n", __func__);
748 if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
749 (r = sshbuf_putf(authctxt->session_info, "%s",
750 authctxt->auth_method_info)) != 0) {
751 fatal("%s: append method info: %s",
752 __func__, ssh_err(r));
753 }
754 }
755 if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
756 fatal("%s: append: %s", __func__, ssh_err(r));
757}
627 758
diff --git a/gss-serv.c b/gss-serv.c
index 53993d674..6cae720e5 100644
--- a/gss-serv.c
+++ b/gss-serv.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: gss-serv.c,v 1.29 2015/05/22 03:50:02 djm Exp $ */ 1/* $OpenBSD: gss-serv.c,v 1.30 2017/06/24 06:34:38 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. 4 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -393,4 +393,13 @@ ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
393 return (ctx->major); 393 return (ctx->major);
394} 394}
395 395
396/* Privileged */
397const 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
diff --git a/monitor.c b/monitor.c
index 8897f6a82..8a7897bde 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.171 2017/05/31 10:04:29 markus Exp $ */ 1/* $OpenBSD: monitor.c,v 1.172 2017/06/24 06:34:38 djm Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -308,6 +308,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
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 */
@@ -347,6 +349,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
347 auth_method, auth_submethod); 349 auth_method, auth_submethod);
348 if (!partial && !authenticated) 350 if (!partial && !authenticated)
349 authctxt->failures++; 351 authctxt->failures++;
352 if (authenticated || partial) {
353 auth2_update_session_info(authctxt,
354 auth_method, auth_submethod);
355 }
350 } 356 }
351 } 357 }
352 358
@@ -1147,12 +1153,11 @@ mm_answer_keyallowed(int sock, Buffer *m)
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";
1157 if (options.pubkey_authentication && 1162 if (options.pubkey_authentication &&
1158 (!pubkey_auth_attempt || allowed != 1)) 1163 (!pubkey_auth_attempt || allowed != 1))
@@ -1160,11 +1165,12 @@ mm_answer_keyallowed(int sock, Buffer *m)
1160 break; 1165 break;
1161 case MM_HOSTKEY: 1166 case MM_HOSTKEY:
1162 allowed = options.hostbased_authentication && 1167 allowed = options.hostbased_authentication &&
1168 !auth2_key_already_used(authctxt, key) &&
1163 match_pattern_list(sshkey_ssh_name(key), 1169 match_pattern_list(sshkey_ssh_name(key),
1164 options.hostbased_key_types, 0) == 1 && 1170 options.hostbased_key_types, 0) == 1 &&
1165 hostbased_key_allowed(authctxt->pw, 1171 hostbased_key_allowed(authctxt->pw,
1166 cuser, chost, key); 1172 cuser, chost, key);
1167 pubkey_auth_info(authctxt, key, 1173 auth2_record_info(authctxt,
1168 "client user \"%.100s\", client host \"%.100s\"", 1174 "client user \"%.100s\", client host \"%.100s\"",
1169 cuser, chost); 1175 cuser, chost);
1170 auth_method = "hostbased"; 1176 auth_method = "hostbased";
@@ -1175,11 +1181,10 @@ mm_answer_keyallowed(int sock, Buffer *m)
1175 } 1181 }
1176 } 1182 }
1177 1183
1178 debug3("%s: key %p is %s", 1184 debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed");
1179 __func__, key, allowed ? "allowed" : "not allowed");
1180 1185
1181 if (key != NULL) 1186 auth2_record_key(authctxt, 0, key);
1182 key_free(key); 1187 sshkey_free(key);
1183 1188
1184 /* clear temporarily storage (used by verify) */ 1189 /* clear temporarily storage (used by verify) */
1185 monitor_reset_key_state(); 1190 monitor_reset_key_state();
@@ -1353,10 +1358,12 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
1353 switch (key_blobtype) { 1358 switch (key_blobtype) {
1354 case MM_USERKEY: 1359 case MM_USERKEY:
1355 valid_data = monitor_valid_userblob(data, datalen); 1360 valid_data = monitor_valid_userblob(data, datalen);
1361 auth_method = "publickey";
1356 break; 1362 break;
1357 case MM_HOSTKEY: 1363 case MM_HOSTKEY:
1358 valid_data = monitor_valid_hostbasedblob(data, datalen, 1364 valid_data = monitor_valid_hostbasedblob(data, datalen,
1359 hostbased_cuser, hostbased_chost); 1365 hostbased_cuser, hostbased_chost);
1366 auth_method = "hostbased";
1360 break; 1367 break;
1361 default: 1368 default:
1362 valid_data = 0; 1369 valid_data = 0;
@@ -1367,23 +1374,17 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
1367 1374
1368 ret = sshkey_verify(key, signature, signaturelen, data, datalen, 1375 ret = sshkey_verify(key, signature, signaturelen, data, datalen,
1369 active_state->compat); 1376 active_state->compat);
1370 debug3("%s: key %p signature %s", 1377 debug3("%s: %s %p signature %s", __func__, auth_method, key,
1371 __func__, key, (ret == 0) ? "verified" : "unverified"); 1378 (ret == 0) ? "verified" : "unverified");
1372 1379 auth2_record_key(authctxt, ret == 0, key);
1373 /* If auth was successful then record key to ensure it isn't reused */
1374 if (ret == 0 && key_blobtype == MM_USERKEY)
1375 auth2_record_userkey(authctxt, key);
1376 else
1377 sshkey_free(key);
1378 1380
1379 free(blob); 1381 free(blob);
1380 free(signature); 1382 free(signature);
1381 free(data); 1383 free(data);
1382 1384
1383 auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
1384
1385 monitor_reset_key_state(); 1385 monitor_reset_key_state();
1386 1386
1387 sshkey_free(key);
1387 sshbuf_reset(m); 1388 sshbuf_reset(m);
1388 1389
1389 /* encode ret != 0 as positive integer, since we're sending u32 */ 1390 /* encode ret != 0 as positive integer, since we're sending u32 */
@@ -1799,6 +1800,7 @@ int
1799mm_answer_gss_userok(int sock, Buffer *m) 1800mm_answer_gss_userok(int sock, Buffer *m)
1800{ 1801{
1801 int authenticated; 1802 int authenticated;
1803 const char *displayname;
1802 1804
1803 if (!options.gss_authentication) 1805 if (!options.gss_authentication)
1804 fatal("%s: GSSAPI authentication not enabled", __func__); 1806 fatal("%s: GSSAPI authentication not enabled", __func__);
@@ -1813,6 +1815,9 @@ mm_answer_gss_userok(int sock, Buffer *m)
1813 1815
1814 auth_method = "gssapi-with-mic"; 1816 auth_method = "gssapi-with-mic";
1815 1817
1818 if ((displayname = ssh_gssapi_displayname()) != NULL)
1819 auth2_record_info(authctxt, "%s", displayname);
1820
1816 /* Monitor loop will terminate if authenticated */ 1821 /* Monitor loop will terminate if authenticated */
1817 return (authenticated); 1822 return (authenticated);
1818} 1823}
diff --git a/servconf.c b/servconf.c
index a112798e4..ed1fc71cf 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.308 2017/05/17 01:24:17 djm Exp $ */ 2/* $OpenBSD: servconf.c,v 1.309 2017/06/24 06:34:38 djm Exp $ */
3/* 3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved 5 * All rights reserved
@@ -164,6 +164,7 @@ initialize_server_options(ServerOptions *options)
164 options->version_addendum = NULL; 164 options->version_addendum = NULL;
165 options->fingerprint_hash = -1; 165 options->fingerprint_hash = -1;
166 options->disable_forwarding = -1; 166 options->disable_forwarding = -1;
167 options->expose_userauth_info = -1;
167} 168}
168 169
169/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 170/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
@@ -333,6 +334,8 @@ fill_default_server_options(ServerOptions *options)
333 options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 334 options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
334 if (options->disable_forwarding == -1) 335 if (options->disable_forwarding == -1)
335 options->disable_forwarding = 0; 336 options->disable_forwarding = 0;
337 if (options->expose_userauth_info == -1)
338 options->expose_userauth_info = 0;
336 339
337 assemble_algorithms(options); 340 assemble_algorithms(options);
338 341
@@ -418,6 +421,7 @@ typedef enum {
418 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, 421 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
419 sStreamLocalBindMask, sStreamLocalBindUnlink, 422 sStreamLocalBindMask, sStreamLocalBindUnlink,
420 sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, 423 sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
424 sExposeAuthInfo,
421 sDeprecated, sIgnore, sUnsupported 425 sDeprecated, sIgnore, sUnsupported
422} ServerOpCodes; 426} ServerOpCodes;
423 427
@@ -561,6 +565,7 @@ static struct {
561 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, 565 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
562 { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, 566 { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
563 { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, 567 { "disableforwarding", sDisableForwarding, SSHCFG_ALL },
568 { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
564 { NULL, sBadOption, 0 } 569 { NULL, sBadOption, 0 }
565}; 570};
566 571
@@ -1835,6 +1840,10 @@ process_server_config_line(ServerOptions *options, char *line,
1835 options->fingerprint_hash = value; 1840 options->fingerprint_hash = value;
1836 break; 1841 break;
1837 1842
1843 case sExposeAuthInfo:
1844 intptr = &options->expose_userauth_info;
1845 goto parse_flag;
1846
1838 case sDeprecated: 1847 case sDeprecated:
1839 case sIgnore: 1848 case sIgnore:
1840 case sUnsupported: 1849 case sUnsupported:
@@ -1973,6 +1982,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1973 M_CP_INTOPT(allow_streamlocal_forwarding); 1982 M_CP_INTOPT(allow_streamlocal_forwarding);
1974 M_CP_INTOPT(allow_agent_forwarding); 1983 M_CP_INTOPT(allow_agent_forwarding);
1975 M_CP_INTOPT(disable_forwarding); 1984 M_CP_INTOPT(disable_forwarding);
1985 M_CP_INTOPT(expose_userauth_info);
1976 M_CP_INTOPT(permit_tun); 1986 M_CP_INTOPT(permit_tun);
1977 M_CP_INTOPT(fwd_opts.gateway_ports); 1987 M_CP_INTOPT(fwd_opts.gateway_ports);
1978 M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); 1988 M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
@@ -2272,6 +2282,7 @@ dump_config(ServerOptions *o)
2272 dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); 2282 dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
2273 dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2283 dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2274 dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); 2284 dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
2285 dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
2275 2286
2276 /* string arguments */ 2287 /* string arguments */
2277 dump_cfg_string(sPidFile, o->pid_file); 2288 dump_cfg_string(sPidFile, o->pid_file);
diff --git a/servconf.h b/servconf.h
index 5853a9747..c2848a765 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.123 2016/11/30 03:00:05 djm Exp $ */ 1/* $OpenBSD: servconf.h,v 1.124 2017/06/24 06:34:38 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -189,6 +189,7 @@ typedef struct {
189 char *auth_methods[MAX_AUTH_METHODS]; 189 char *auth_methods[MAX_AUTH_METHODS];
190 190
191 int fingerprint_hash; 191 int fingerprint_hash;
192 int expose_userauth_info;
192} ServerOptions; 193} ServerOptions;
193 194
194/* Information about the incoming connection as used by Match */ 195/* Information about the incoming connection as used by Match */
diff --git a/session.c b/session.c
index 295204c6e..a2588e74b 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.c,v 1.289 2017/06/24 05:24:11 djm Exp $ */ 1/* $OpenBSD: session.c,v 1.290 2017/06/24 06:34:38 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -94,6 +94,7 @@
94#include "kex.h" 94#include "kex.h"
95#include "monitor_wrap.h" 95#include "monitor_wrap.h"
96#include "sftp.h" 96#include "sftp.h"
97#include "atomicio.h"
97 98
98#if defined(KRB5) && defined(USE_AFS) 99#if defined(KRB5) && defined(USE_AFS)
99#include <kafs.h> 100#include <kafs.h>
@@ -160,6 +161,9 @@ login_cap_t *lc;
160static int is_child = 0; 161static int is_child = 0;
161static int in_chroot = 0; 162static int in_chroot = 0;
162 163
164/* File containing userauth info, if ExposeAuthInfo set */
165static char *auth_info_file = NULL;
166
163/* Name and directory of socket for authentication agent forwarding. */ 167/* Name and directory of socket for authentication agent forwarding. */
164static char *auth_sock_name = NULL; 168static char *auth_sock_name = NULL;
165static char *auth_sock_dir = NULL; 169static char *auth_sock_dir = NULL;
@@ -249,6 +253,40 @@ display_loginmsg(void)
249 } 253 }
250} 254}
251 255
256static void
257prepare_auth_info_file(struct passwd *pw, struct sshbuf *info)
258{
259 int fd = -1, success = 0;
260
261 if (!options.expose_userauth_info || info == NULL)
262 return;
263
264 temporarily_use_uid(pw);
265 auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX");
266 if ((fd = mkstemp(auth_info_file)) == -1) {
267 error("%s: mkstemp: %s", __func__, strerror(errno));
268 goto out;
269 }
270 if (atomicio(vwrite, fd, sshbuf_mutable_ptr(info),
271 sshbuf_len(info)) != sshbuf_len(info)) {
272 error("%s: write: %s", __func__, strerror(errno));
273 goto out;
274 }
275 if (close(fd) != 0) {
276 error("%s: close: %s", __func__, strerror(errno));
277 goto out;
278 }
279 success = 1;
280 out:
281 if (!success) {
282 if (fd != -1)
283 close(fd);
284 free(auth_info_file);
285 auth_info_file = NULL;
286 }
287 restore_uid();
288}
289
252void 290void
253do_authenticated(Authctxt *authctxt) 291do_authenticated(Authctxt *authctxt)
254{ 292{
@@ -264,7 +302,10 @@ do_authenticated(Authctxt *authctxt)
264 302
265 auth_debug_send(); 303 auth_debug_send();
266 304
305 prepare_auth_info_file(authctxt->pw, authctxt->session_info);
306
267 do_authenticated2(authctxt); 307 do_authenticated2(authctxt);
308
268 do_cleanup(authctxt); 309 do_cleanup(authctxt);
269} 310}
270 311
@@ -1077,6 +1118,8 @@ do_setup_env(Session *s, const char *shell)
1077 free(laddr); 1118 free(laddr);
1078 child_set_env(&env, &envsize, "SSH_CONNECTION", buf); 1119 child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
1079 1120
1121 if (auth_info_file != NULL)
1122 child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info_file);
1080 if (s->ttyfd != -1) 1123 if (s->ttyfd != -1)
1081 child_set_env(&env, &envsize, "SSH_TTY", s->tty); 1124 child_set_env(&env, &envsize, "SSH_TTY", s->tty);
1082 if (s->term) 1125 if (s->term)
@@ -2549,6 +2592,15 @@ do_cleanup(Authctxt *authctxt)
2549 /* remove agent socket */ 2592 /* remove agent socket */
2550 auth_sock_cleanup_proc(authctxt->pw); 2593 auth_sock_cleanup_proc(authctxt->pw);
2551 2594
2595 /* remove userauth info */
2596 if (auth_info_file != NULL) {
2597 temporarily_use_uid(authctxt->pw);
2598 unlink(auth_info_file);
2599 restore_uid();
2600 free(auth_info_file);
2601 auth_info_file = NULL;
2602 }
2603
2552 /* 2604 /*
2553 * Cleanup ptys/utmp only if privsep is disabled, 2605 * Cleanup ptys/utmp only if privsep is disabled,
2554 * or if running in monitor. 2606 * or if running in monitor.
diff --git a/ssh-gss.h b/ssh-gss.h
index a99d7f08b..6593e422d 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */ 1/* $OpenBSD: ssh-gss.h,v 1.12 2017/06/24 06:34:38 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. 3 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
4 * 4 *
@@ -128,6 +128,7 @@ OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
128void ssh_gssapi_do_child(char ***, u_int *); 128void ssh_gssapi_do_child(char ***, u_int *);
129void ssh_gssapi_cleanup_creds(void); 129void ssh_gssapi_cleanup_creds(void);
130void ssh_gssapi_storecreds(void); 130void ssh_gssapi_storecreds(void);
131const char *ssh_gssapi_displayname(void);
131 132
132#endif /* GSSAPI */ 133#endif /* GSSAPI */
133 134
diff --git a/sshd_config.5 b/sshd_config.5
index 7b4cb1d9a..cfe1db82a 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: sshd_config.5,v 1.245 2017/05/17 01:24:17 djm Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.246 2017/06/24 06:34:38 djm Exp $
37.Dd $Mdocdate: May 17 2017 $ 37.Dd $Mdocdate: June 24 2017 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -564,6 +564,12 @@ Disables all forwarding features, including X11,
564TCP and StreamLocal. 564TCP and StreamLocal.
565This option overrides all other forwarding-related options and may 565This option overrides all other forwarding-related options and may
566simplify restricted configurations. 566simplify restricted configurations.
567.It Cm ExposeAuthInfo
568Enables writing a file containing a list of authentication methods and
569public credentials (e.g. keys) used to authenticate the user.
570The location of the file is exposed to the user session though the
571.Ev SSH_AUTH_INFO
572enviornment variable.
567.It Cm FingerprintHash 573.It Cm FingerprintHash
568Specifies the hash algorithm used when logging key fingerprints. 574Specifies the hash algorithm used when logging key fingerprints.
569Valid options are: 575Valid options are: