1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +00:00

Retain permitted methods list in userauth layer state.

There are situations - or _should_ be, at any rate - in which we
terminate a userauth attempt without having received a
USERAUTH_FAILURE from the server, which means that we can't depend on
always starting a userauth loop iteration by extracting the server's
list of permitted methods from the current failure message. If there
isn't a current failure message, the best we can do is remember the
state from last time.

That's already what we do for actually deciding which methods to
attempt (we set s->can_foo from the methods string). But we should
also keep the full original version of the string, for use in error
message.
This commit is contained in:
Simon Tatham 2018-12-06 18:06:15 +00:00
parent 66b776ae6e
commit 6002b272f4

View File

@ -53,6 +53,7 @@ struct ssh2_userauth_state {
Ssh_gss_buf gss_rcvtok, gss_sndtok; Ssh_gss_buf gss_rcvtok, gss_sndtok;
Ssh_gss_stat gss_stat; Ssh_gss_stat gss_stat;
#endif #endif
strbuf *last_methods_string;
bool kbd_inter_refused; bool kbd_inter_refused;
prompts_t *cur_prompt; prompts_t *cur_prompt;
int num_prompts; int num_prompts;
@ -135,6 +136,7 @@ PacketProtocolLayer *ssh2_userauth_new(
s->try_gssapi_kex_auth = try_gssapi_kex_auth; s->try_gssapi_kex_auth = try_gssapi_kex_auth;
s->gssapi_fwd = gssapi_fwd; s->gssapi_fwd = gssapi_fwd;
s->shgss = shgss; s->shgss = shgss;
s->last_methods_string = strbuf_new();
bufchain_init(&s->banner); bufchain_init(&s->banner);
return &s->ppl; return &s->ppl;
@ -164,6 +166,7 @@ static void ssh2_userauth_free(PacketProtocolLayer *ppl)
sfree(s->default_username); sfree(s->default_username);
sfree(s->hostname); sfree(s->hostname);
sfree(s->fullhostname); sfree(s->fullhostname);
strbuf_free(s->last_methods_string);
sfree(s); sfree(s);
} }
@ -427,11 +430,6 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
} }
while (1) { while (1) {
ptrlen methods;
methods.ptr = "";
methods.len = 0;
/* /*
* Wait for the result of the last authentication request. * Wait for the result of the last authentication request.
*/ */
@ -490,8 +488,10 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
* helpfully try next. * helpfully try next.
*/ */
if (pktin->type == SSH2_MSG_USERAUTH_FAILURE) { if (pktin->type == SSH2_MSG_USERAUTH_FAILURE) {
methods = get_string(pktin); ptrlen methods = get_string(pktin);
if (!get_bool(pktin)) { bool partial_success = get_bool(pktin);
if (!partial_success) {
/* /*
* We have received an unequivocal Access * We have received an unequivocal Access
* Denied. This can translate to a variety of * Denied. This can translate to a variety of
@ -558,6 +558,15 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
ppl_logevent(("Further authentication required")); ppl_logevent(("Further authentication required"));
} }
/*
* Save the methods string for use in error messages.
*/
s->last_methods_string->len = 0;
put_data(s->last_methods_string, methods.ptr, methods.len);
/*
* Scan it for method identifiers we know about.
*/
s->can_pubkey = s->can_pubkey =
in_commasep_string("publickey", methods.ptr, methods.len); in_commasep_string("publickey", methods.ptr, methods.len);
s->can_passwd = s->can_passwd =
@ -1488,8 +1497,8 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
"No supported authentication methods available", "No supported authentication methods available",
SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE); SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE);
ssh_sw_abort(s->ppl.ssh, "No supported authentication methods " ssh_sw_abort(s->ppl.ssh, "No supported authentication methods "
"available (server sent: %.*s)", "available (server sent: %s)",
PTRLEN_PRINTF(methods)); s->last_methods_string->s);
return; return;
} }