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

userauth2: add a missing free_prompts().

If a userauth layer is destroyed while userpass input is still
ongoing, ssh2_userauth_free forgot to free the active prompts_t,
leaking memory.

But adding the missing free_prompts call to ssh2_userauth_free results
in a double-free, because another thing I forgot was to null out that
pointer field everywhere _else_ it's freed. Fixed that too.
This commit is contained in:
Simon Tatham 2021-09-16 09:27:25 +01:00
parent 99b4229abf
commit 7a02234353

View File

@ -193,6 +193,8 @@ static void ssh2_userauth_free(PacketProtocolLayer *ppl)
sfree(s->locally_allocated_username); sfree(s->locally_allocated_username);
sfree(s->hostname); sfree(s->hostname);
sfree(s->fullhostname); sfree(s->fullhostname);
if (s->cur_prompt)
free_prompts(s->cur_prompt);
sfree(s->publickey_comment); sfree(s->publickey_comment);
sfree(s->publickey_algorithm); sfree(s->publickey_algorithm);
if (s->publickey_blob) if (s->publickey_blob)
@ -455,6 +457,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
* Terminate. * Terminate.
*/ */
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
ssh_user_close(s->ppl.ssh, "No username provided"); ssh_user_close(s->ppl.ssh, "No username provided");
return; return;
} }
@ -462,6 +465,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
s->username = s->locally_allocated_username = s->username = s->locally_allocated_username =
prompt_get_result(s->cur_prompt->prompts[0]); prompt_get_result(s->cur_prompt->prompts[0]);
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
} else { } else {
if (seat_verbose(s->ppl.seat) || seat_interactive(s->ppl.seat)) if (seat_verbose(s->ppl.seat) || seat_interactive(s->ppl.seat))
ppl_printf("Using username \"%s\".\r\n", s->username); ppl_printf("Using username \"%s\".\r\n", s->username);
@ -918,6 +922,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
if (!s->userpass_ret) { if (!s->userpass_ret) {
/* Failed to get a passphrase. Terminate. */ /* Failed to get a passphrase. Terminate. */
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
ssh_bpp_queue_disconnect( ssh_bpp_queue_disconnect(
s->ppl.bpp, "Unable to authenticate", s->ppl.bpp, "Unable to authenticate",
SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER); SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
@ -928,6 +933,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
passphrase = passphrase =
prompt_get_result(s->cur_prompt->prompts[0]); prompt_get_result(s->cur_prompt->prompts[0]);
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
} else { } else {
passphrase = NULL; /* no passphrase needed */ passphrase = NULL; /* no passphrase needed */
} }
@ -1397,6 +1403,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
* Failed to get responses. Terminate. * Failed to get responses. Terminate.
*/ */
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
ssh_bpp_queue_disconnect( ssh_bpp_queue_disconnect(
s->ppl.bpp, "Unable to authenticate", s->ppl.bpp, "Unable to authenticate",
SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER); SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
@ -1424,6 +1431,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
* when we return to the top of this while loop. * when we return to the top of this while loop.
*/ */
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
/* /*
* Get the next packet in case it's another * Get the next packet in case it's another
@ -1476,6 +1484,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
* Failed to get responses. Terminate. * Failed to get responses. Terminate.
*/ */
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
ssh_bpp_queue_disconnect( ssh_bpp_queue_disconnect(
s->ppl.bpp, "Unable to authenticate", s->ppl.bpp, "Unable to authenticate",
SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER); SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
@ -1489,6 +1498,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
*/ */
s->password = prompt_get_result(s->cur_prompt->prompts[0]); s->password = prompt_get_result(s->cur_prompt->prompts[0]);
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
/* /*
* Send the password packet. * Send the password packet.
@ -1587,6 +1597,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
*/ */
/* burn the evidence */ /* burn the evidence */
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
smemclr(s->password, strlen(s->password)); smemclr(s->password, strlen(s->password));
sfree(s->password); sfree(s->password);
ssh_bpp_queue_disconnect( ssh_bpp_queue_disconnect(
@ -1638,6 +1649,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
put_stringz(s->pktout, prompt_get_result_ref( put_stringz(s->pktout, prompt_get_result_ref(
s->cur_prompt->prompts[1])); s->cur_prompt->prompts[1]));
free_prompts(s->cur_prompt); free_prompts(s->cur_prompt);
s->cur_prompt = NULL;
s->pktout->minlen = 256; s->pktout->minlen = 256;
pq_push(s->ppl.out_pq, s->pktout); pq_push(s->ppl.out_pq, s->pktout);
ppl_logevent("Sent new password"); ppl_logevent("Sent new password");