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

I broke the ability to cope with multiple consecutive k-i INFO_REQUESTS

in r6437. This ought to be better (but I can't test that case).

[originally from svn r6451]
[r6437 == 8719f92c14]
This commit is contained in:
Jacob Nevins 2005-11-09 23:19:33 +00:00
parent 29f1ae8a7e
commit c4b2b493ff

181
ssh.c
View File

@ -7153,9 +7153,6 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
/*
* Keyboard-interactive authentication.
*/
char *name, *inst, *lang;
int name_len, inst_len, lang_len;
int i;
s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
@ -7175,7 +7172,9 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_USERAUTH_INFO_REQUEST) {
/* Server is not willing to do keyboard-interactive
* at all. Give up on it entirely. */
* at all (or, bizarrely but legally, accepts the
* user without actually issuing any prompts).
* Give up on it entirely. */
s->gotit = TRUE;
if (pktin->type == SSH2_MSG_USERAUTH_FAILURE)
logevent("Keyboard-interactive authentication refused");
@ -7185,89 +7184,113 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
}
/*
* We've got a fresh USERAUTH_INFO_REQUEST.
* Get the preamble and start building a prompt.
* Loop while the server continues to send INFO_REQUESTs.
*/
ssh_pkt_getstring(pktin, &name, &name_len);
ssh_pkt_getstring(pktin, &inst, &inst_len);
ssh_pkt_getstring(pktin, &lang, &lang_len);
s->cur_prompt = new_prompts(ssh->frontend);
s->cur_prompt->to_server = TRUE;
if (name_len) {
/* FIXME: better prefix to distinguish from
* local prompts? */
s->cur_prompt->name = dupprintf("SSH server: %.*s",
name_len, name);
s->cur_prompt->name_reqd = TRUE;
} else {
s->cur_prompt->name = dupstr("SSH server authentication");
s->cur_prompt->name_reqd = FALSE;
}
s->cur_prompt->instruction =
dupprintf("Using keyboard-interactive authentication.%s%.*s",
inst_len ? "\n" : "", inst_len, inst);
s->cur_prompt->instr_reqd = TRUE;
while (pktin->type == SSH2_MSG_USERAUTH_INFO_REQUEST) {
/*
* Get the prompts from the packet.
*/
s->num_prompts = ssh_pkt_getuint32(pktin);
for (i = 0; i < s->num_prompts; i++) {
char *prompt;
int prompt_len;
int echo;
static char noprompt[] =
"<server failed to send prompt>: ";
char *name, *inst, *lang;
int name_len, inst_len, lang_len;
int i;
ssh_pkt_getstring(pktin, &prompt, &prompt_len);
echo = ssh2_pkt_getbool(pktin);
if (!prompt_len) {
prompt = noprompt;
prompt_len = lenof(noprompt)-1;
/*
* We've got a fresh USERAUTH_INFO_REQUEST.
* Get the preamble and start building a prompt.
*/
ssh_pkt_getstring(pktin, &name, &name_len);
ssh_pkt_getstring(pktin, &inst, &inst_len);
ssh_pkt_getstring(pktin, &lang, &lang_len);
s->cur_prompt = new_prompts(ssh->frontend);
s->cur_prompt->to_server = TRUE;
if (name_len) {
/* FIXME: better prefix to distinguish from
* local prompts? */
s->cur_prompt->name =
dupprintf("SSH server: %.*s", name_len, name);
s->cur_prompt->name_reqd = TRUE;
} else {
s->cur_prompt->name =
dupstr("SSH server authentication");
s->cur_prompt->name_reqd = FALSE;
}
add_prompt(s->cur_prompt,
dupprintf("%.*s", prompt_len, prompt),
echo, SSH_MAX_PASSWORD_LEN);
/* FIXME: ugly to print "Using..." in prompt _every_
* time round. Can this be done more subtly? */
s->cur_prompt->instruction =
dupprintf("Using keyboard-interactive authentication.%s%.*s",
inst_len ? "\n" : "", inst_len, inst);
s->cur_prompt->instr_reqd = TRUE;
/*
* Get the prompts from the packet.
*/
s->num_prompts = ssh_pkt_getuint32(pktin);
for (i = 0; i < s->num_prompts; i++) {
char *prompt;
int prompt_len;
int echo;
static char noprompt[] =
"<server failed to send prompt>: ";
ssh_pkt_getstring(pktin, &prompt, &prompt_len);
echo = ssh2_pkt_getbool(pktin);
if (!prompt_len) {
prompt = noprompt;
prompt_len = lenof(noprompt)-1;
}
add_prompt(s->cur_prompt,
dupprintf("%.*s", prompt_len, prompt),
echo, SSH_MAX_PASSWORD_LEN);
}
/*
* Get the user's responses.
*/
if (s->num_prompts) {
int ret; /* not live over crReturn */
ret = get_userpass_input(s->cur_prompt, NULL, 0);
while (ret < 0) {
ssh->send_ok = 1;
crWaitUntilV(!pktin);
ret = get_userpass_input(s->cur_prompt, in, inlen);
ssh->send_ok = 0;
}
if (!ret) {
/*
* Failed to get responses. Terminate.
*/
free_prompts(s->cur_prompt);
ssh_disconnect(ssh, NULL, "Unable to authenticate",
SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
TRUE);
crStopV;
}
}
/*
* Send the responses to the server.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_INFO_RESPONSE);
s->pktout->forcepad = 256;
ssh2_pkt_adduint32(s->pktout, s->num_prompts);
for (i=0; i < s->num_prompts; i++) {
dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
ssh2_pkt_addstring(s->pktout,
s->cur_prompt->prompts[i]->result);
end_log_omission(ssh, s->pktout);
}
ssh2_pkt_send(ssh, s->pktout);
/*
* Get the next packet in case it's another
* INFO_REQUEST.
*/
crWaitUntilV(pktin);
}
/*
* Get the user's responses.
* We should have SUCCESS or FAILURE now.
*/
if (s->num_prompts) {
int ret; /* not live over crReturn */
ret = get_userpass_input(s->cur_prompt, NULL, 0);
while (ret < 0) {
ssh->send_ok = 1;
crWaitUntilV(!pktin);
ret = get_userpass_input(s->cur_prompt, in, inlen);
ssh->send_ok = 0;
}
if (!ret) {
/*
* Failed to get responses. Terminate.
*/
free_prompts(s->cur_prompt);
ssh_disconnect(ssh, NULL, "Unable to authenticate",
SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
TRUE);
crStopV;
}
}
/*
* Send the responses to the server.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_INFO_RESPONSE);
s->pktout->forcepad = 256;
ssh2_pkt_adduint32(s->pktout, s->num_prompts);
for (i=0; i < s->num_prompts; i++) {
dont_log_password(ssh, s->pktout, PKTLOG_BLANK);
ssh2_pkt_addstring(s->pktout,
s->cur_prompt->prompts[i]->result);
end_log_omission(ssh, s->pktout);
}
ssh2_pkt_send(ssh, s->pktout);
s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
s->gotit = TRUE;
} else if (s->can_passwd) {