From b8e3173d5169da33af5b41fa3b8e5b482bfdc6dc Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 9 Nov 2005 23:19:33 +0000 Subject: [PATCH] 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). git-svn-id: svn://svn.tartarus.org/sgt/putty@6451 cda61777-01e9-0310-a592-d414129be87e --- ssh.c | 175 +++++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 99 insertions(+), 76 deletions(-) diff --git a/ssh.c b/ssh.c index 71388a36..1e228446 100644 --- a/ssh.c +++ b/ssh.c @@ -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[] = - ": "; + 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 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; + /* + * 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[] = + ": "; + + 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); } - 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; + + /* + * 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); + } /* - * Send the responses to the server. + * We should have SUCCESS or FAILURE now. */ - 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) { -- 2.11.0