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

Restructure some loops with crReturn in them.

A large part of the purpose of the 20-patch series just past is to
arrange that user input is never dropped on the floor: if you type it
at a moment where the active protocol coroutine has nothing it can
usefully do with it, the default action will now be to leave it on the
user_input queue where it will eventually be picked up by some later
coroutine, or later phase of this one, that does.

And did I _test_ this feature, end to end, just once, before pushing
the giant patch series?

I did not.

It doesn't work, and the reason why it doesn't work is because various
loops that spin round alternating a crReturn with a check of the input
queue do the first crReturn _before_ the first queue check. So if
there's already data in the queue, well, it won't be _dropped_, but it
also won't be passed on immediately to where it needs to be - instead,
it will sit in the queue until you press _another_ key, at which point
a queue check will happen and all your backed-up typeahead data will
come out.

Fixed by restructuring those loops to do a queue check first. This
applies to the final loop in do_ssh2_connection, and all the little
loops during userauth that prompt for usernames, passwords,
passphrases etc via get_userpass_input.
This commit is contained in:
Simon Tatham 2018-05-18 11:01:12 +01:00
parent ea7f3c2abc
commit d294d1d0dc

96
ssh.c
View File

@ -4551,13 +4551,17 @@ static void do_ssh1_login(void *vctx)
s->cur_prompt->name = dupstr("SSH login name");
add_prompt(s->cur_prompt, dupstr("login as: "), TRUE);
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
while (s->userpass_ret < 0) {
ssh->send_ok = 1;
crReturnV;
while (1) {
while (s->userpass_ret < 0 &&
bufchain_size(&ssh->user_input) > 0)
s->userpass_ret = get_userpass_input(
s->cur_prompt, &ssh->user_input);
if (s->userpass_ret >= 0)
break;
ssh->send_ok = 1;
crReturnV;
ssh->send_ok = 0;
}
if (!s->userpass_ret) {
@ -4849,13 +4853,17 @@ static void do_ssh1_login(void *vctx)
dupprintf("Passphrase for key \"%.100s\": ",
s->publickey_comment), FALSE);
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
while (s->userpass_ret < 0) {
ssh->send_ok = 1;
crReturnV;
while (1) {
while (s->userpass_ret < 0 &&
bufchain_size(&ssh->user_input) > 0)
s->userpass_ret = get_userpass_input(
s->cur_prompt, &ssh->user_input);
if (s->userpass_ret >= 0)
break;
ssh->send_ok = 1;
crReturnV;
ssh->send_ok = 0;
}
if (!s->userpass_ret) {
@ -5072,13 +5080,17 @@ static void do_ssh1_login(void *vctx)
* authentication.
*/
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
while (s->userpass_ret < 0) {
ssh->send_ok = 1;
crReturnV;
while (1) {
while (s->userpass_ret < 0 &&
bufchain_size(&ssh->user_input) > 0)
s->userpass_ret = get_userpass_input(
s->cur_prompt, &ssh->user_input);
if (s->userpass_ret >= 0)
break;
ssh->send_ok = 1;
crReturnV;
ssh->send_ok = 0;
}
if (!s->userpass_ret) {
@ -10315,13 +10327,17 @@ static void do_ssh2_userauth(void *vctx)
s->cur_prompt->name = dupstr("SSH login name");
add_prompt(s->cur_prompt, dupstr("login as: "), TRUE);
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
while (s->userpass_ret < 0) {
ssh->send_ok = 1;
crReturnV;
while (1) {
while (s->userpass_ret < 0 &&
bufchain_size(&ssh->user_input) > 0)
s->userpass_ret = get_userpass_input(
s->cur_prompt, &ssh->user_input);
if (s->userpass_ret >= 0)
break;
ssh->send_ok = 1;
crReturnV;
ssh->send_ok = 0;
}
if (!s->userpass_ret) {
@ -10745,14 +10761,17 @@ static void do_ssh2_userauth(void *vctx)
FALSE);
s->userpass_ret = get_userpass_input(
s->cur_prompt, NULL);
while (s->userpass_ret < 0) {
ssh->send_ok = 1;
crReturnV;
while (1) {
while (s->userpass_ret < 0 &&
bufchain_size(&ssh->user_input) > 0) {
bufchain_size(&ssh->user_input) > 0)
s->userpass_ret = get_userpass_input(
s->cur_prompt, &ssh->user_input);
}
if (s->userpass_ret >= 0)
break;
ssh->send_ok = 1;
crReturnV;
ssh->send_ok = 0;
}
if (!s->userpass_ret) {
@ -11131,14 +11150,17 @@ static void do_ssh2_userauth(void *vctx)
* response(s).
*/
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
while (s->userpass_ret < 0) {
ssh->send_ok = 1;
crReturnV;
while (1) {
while (s->userpass_ret < 0 &&
bufchain_size(&ssh->user_input) > 0) {
bufchain_size(&ssh->user_input) > 0)
s->userpass_ret = get_userpass_input(
s->cur_prompt, &ssh->user_input);
}
if (s->userpass_ret >= 0)
break;
ssh->send_ok = 1;
crReturnV;
ssh->send_ok = 0;
}
if (!s->userpass_ret) {
@ -11201,14 +11223,17 @@ static void do_ssh2_userauth(void *vctx)
FALSE);
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
while (s->userpass_ret < 0) {
ssh->send_ok = 1;
crReturnV;
while (1) {
while (s->userpass_ret < 0 &&
bufchain_size(&ssh->user_input) > 0) {
bufchain_size(&ssh->user_input) > 0)
s->userpass_ret = get_userpass_input(
s->cur_prompt, &ssh->user_input);
}
if (s->userpass_ret >= 0)
break;
ssh->send_ok = 1;
crReturnV;
ssh->send_ok = 0;
}
if (!s->userpass_ret) {
@ -11315,16 +11340,17 @@ static void do_ssh2_userauth(void *vctx)
while (!got_new) {
s->userpass_ret = get_userpass_input(
s->cur_prompt, NULL);
while (s->userpass_ret < 0) {
ssh->send_ok = 1;
crReturnV;
while (1) {
while (s->userpass_ret < 0 &&
bufchain_size(&ssh->user_input) > 0) {
bufchain_size(&ssh->user_input) > 0)
s->userpass_ret = get_userpass_input(
s->cur_prompt, &ssh->user_input);
if (s->userpass_ret >= 0)
break;
}
if (s->userpass_ret >= 0)
break;
ssh->send_ok = 1;
crReturnV;
ssh->send_ok = 0;
}
if (!s->userpass_ret) {
@ -11743,7 +11769,6 @@ static void do_ssh2_connection(void *vctx)
if (ssh->mainchan)
ssh->send_ok = 1;
while (1) {
crReturnV;
if ((pktin = pq_pop(&ssh->pq_ssh2_connection)) != NULL) {
/*
@ -11765,6 +11790,7 @@ static void do_ssh2_connection(void *vctx)
ssh_send_channel_data(ssh->mainchan, data, len);
bufchain_consume(&ssh->user_input, len);
}
crReturnV;
}
crFinishV;