X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/fd5e5847eb0f834ce8124f0574bd3cfaf878db53..3ad9d396e3e57477b4da4b20665ca33edd5d7f67:/ssh.c diff --git a/ssh.c b/ssh.c index 2c538239..c03cd6db 100644 --- a/ssh.c +++ b/ssh.c @@ -507,7 +507,7 @@ static int ssh_rportcmp_ssh2(void *av, void *bv) { struct ssh_rportfwd *a = (struct ssh_rportfwd *) av; struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv; - int i; + if (a->sport > b->sport) return +1; if (a->sport < b->sport) @@ -1686,6 +1686,11 @@ static char *connect_to_host(char *host, int port, char **realhost) /* * Try to find host. */ + { + char buf[200]; + sprintf(buf, "Looking up host \"%.170s\"", host); + logevent(buf); + } addr = sk_namelookup(host, realhost); if ((err = sk_addr_error(addr))) return err; @@ -1697,6 +1702,12 @@ static char *connect_to_host(char *host, int port, char **realhost) /* * Open socket. */ + { + char buf[200], addrbuf[100]; + sk_getaddr(addr, addrbuf, 100); + sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); + logevent(buf); + } s = sk_new(addr, port, 0, 1, &fn_table_ptr); if ((err = sk_socket_error(s))) return err; @@ -2709,7 +2720,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) int bufsize = from_backend(pktin.type == SSH1_SMSG_STDERR_DATA, pktin.body + 4, len); - if (bufsize > SSH1_BUFFER_LIMIT) { + if (!ssh1_stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) { ssh1_stdout_throttling = 1; ssh1_throttle(+1); } @@ -2841,6 +2852,19 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) pfd_confirm(c->u.pfd.s); } + } else if (pktin.type == SSH1_MSG_CHANNEL_OPEN_FAILURE) { + unsigned int remoteid = GET_32BIT(pktin.body); + unsigned int localid = GET_32BIT(pktin.body+4); + struct ssh_channel *c; + + c = find234(ssh_channels, &remoteid, ssh_channelfind); + if (c && c->type == CHAN_SOCKDATA_DORMANT) { + logevent("Forwarded connection refused by server"); + pfd_close(c->u.pfd.s); + del234(ssh_channels, c); + sfree(c); + } + } else if (pktin.type == SSH1_MSG_CHANNEL_CLOSE || pktin.type == SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION) { /* Remote side closes a channel. */ @@ -2942,7 +2966,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) bufsize = 0; /* agent channels never back up */ break; } - if (bufsize > SSH1_BUFFER_LIMIT) { + if (!c->v.v1.throttling && bufsize > SSH1_BUFFER_LIMIT) { c->v.v1.throttling = 1; ssh1_throttle(+1); } @@ -3793,66 +3817,12 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) in_commasep_string("publickey", methods, methlen); can_passwd = in_commasep_string("password", methods, methlen); - can_passwd = - in_commasep_string("password", methods, methlen); can_keyb_inter = in_commasep_string("keyboard-interactive", methods, methlen); } method = 0; - if (!method && can_keyb_inter && !tried_keyb_inter) { - method = AUTH_KEYBOARD_INTERACTIVE; - type = AUTH_TYPE_KEYBOARD_INTERACTIVE; - tried_keyb_inter = TRUE; - - ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST); - ssh2_pkt_addstring(username); - ssh2_pkt_addstring("ssh-connection"); /* service requested */ - ssh2_pkt_addstring("keyboard-interactive"); /* method */ - ssh2_pkt_addstring(""); /* lang */ - ssh2_pkt_addstring(""); - ssh2_pkt_send(); - - crWaitUntilV(ispkt); - if (pktin.type != SSH2_MSG_USERAUTH_INFO_REQUEST) { - if (pktin.type == SSH2_MSG_USERAUTH_FAILURE) - gotit = TRUE; - logevent("Keyboard-interactive authentication refused"); - type = AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET; - continue; - } - - kbd_inter_running = TRUE; - } - - if (kbd_inter_running) { - method = AUTH_KEYBOARD_INTERACTIVE; - type = AUTH_TYPE_KEYBOARD_INTERACTIVE; - tried_keyb_inter = TRUE; - - /* We've got packet with that "interactive" info - dump banners, and set its prompt as ours */ - { - char *name, *inst, *lang, *prompt; - int name_len, inst_len, lang_len, prompt_len; - ssh2_pkt_getstring(&name, &name_len); - ssh2_pkt_getstring(&inst, &inst_len); - ssh2_pkt_getstring(&lang, &lang_len); - if (name_len > 0) - c_write_untrusted(name, name_len); - if (inst_len > 0) - c_write_untrusted(inst, inst_len); - num_prompts = ssh2_pkt_getuint32(); - - ssh2_pkt_getstring(&prompt, &prompt_len); - strncpy(pwprompt, prompt, sizeof(pwprompt)); - need_pw = TRUE; - - echo = ssh2_pkt_getbool(); - } - } - if (!method && can_pubkey && agent_exists() && !tried_agent) { /* * Attempt public-key authentication using Pageant. @@ -4046,6 +4016,58 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) } } + if (!method && can_keyb_inter && !tried_keyb_inter) { + method = AUTH_KEYBOARD_INTERACTIVE; + type = AUTH_TYPE_KEYBOARD_INTERACTIVE; + tried_keyb_inter = TRUE; + + ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST); + ssh2_pkt_addstring(username); + ssh2_pkt_addstring("ssh-connection"); /* service requested */ + ssh2_pkt_addstring("keyboard-interactive"); /* method */ + ssh2_pkt_addstring(""); /* lang */ + ssh2_pkt_addstring(""); + ssh2_pkt_send(); + + crWaitUntilV(ispkt); + if (pktin.type != SSH2_MSG_USERAUTH_INFO_REQUEST) { + if (pktin.type == SSH2_MSG_USERAUTH_FAILURE) + gotit = TRUE; + logevent("Keyboard-interactive authentication refused"); + type = AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET; + continue; + } + + kbd_inter_running = TRUE; + } + + if (kbd_inter_running) { + method = AUTH_KEYBOARD_INTERACTIVE; + type = AUTH_TYPE_KEYBOARD_INTERACTIVE; + tried_keyb_inter = TRUE; + + /* We've got packet with that "interactive" info + dump banners, and set its prompt as ours */ + { + char *name, *inst, *lang, *prompt; + int name_len, inst_len, lang_len, prompt_len; + ssh2_pkt_getstring(&name, &name_len); + ssh2_pkt_getstring(&inst, &inst_len); + ssh2_pkt_getstring(&lang, &lang_len); + if (name_len > 0) + c_write_untrusted(name, name_len); + if (inst_len > 0) + c_write_untrusted(inst, inst_len); + num_prompts = ssh2_pkt_getuint32(); + + ssh2_pkt_getstring(&prompt, &prompt_len); + strncpy(pwprompt, prompt, sizeof(pwprompt)); + need_pw = TRUE; + + echo = ssh2_pkt_getbool(); + } + } + if (!method && can_passwd) { method = AUTH_PASSWORD; sprintf(pwprompt, "%.90s@%.90s's password: ", username, @@ -4716,22 +4738,29 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) c = find234(ssh_channels, &i, ssh_channelfind); if (!c) continue; /* nonexistent channel */ - if (c->closes == 0) { - ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE); - ssh2_pkt_adduint32(c->remoteid); - ssh2_pkt_send(); - } /* Do pre-close processing on the channel. */ switch (c->type) { case CHAN_MAINSESSION: break; /* nothing to see here, move along */ case CHAN_X11: + if (c->u.x11.s != NULL) + x11_close(c->u.x11.s); + sshfwd_close(c); break; case CHAN_AGENT: + sshfwd_close(c); break; case CHAN_SOCKDATA: + if (c->u.pfd.s != NULL) + pfd_close(c->u.pfd.s); + sshfwd_close(c); break; } + if (c->closes == 0) { + ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE); + ssh2_pkt_adduint32(c->remoteid); + ssh2_pkt_send(); + } del234(ssh_channels, c); bufchain_clear(&c->v.v2.outbuffer); sfree(c); @@ -4773,6 +4802,21 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) c->v.v2.remmaxpkt = ssh2_pkt_getuint32(); bufchain_init(&c->v.v2.outbuffer); pfd_confirm(c->u.pfd.s); + } else if (pktin.type == SSH2_MSG_CHANNEL_OPEN_FAILURE) { + unsigned i = ssh2_pkt_getuint32(); + struct ssh_channel *c; + c = find234(ssh_channels, &i, ssh_channelfind); + if (!c) + continue; /* nonexistent channel */ + if (c->type != CHAN_SOCKDATA_DORMANT) + continue; /* dunno why they're failing this */ + + logevent("Forwarded connection refused by server"); + + pfd_close(c->u.pfd.s); + + del234(ssh_channels, c); + sfree(c); } else if (pktin.type == SSH2_MSG_CHANNEL_OPEN) { char *type; int typelen; @@ -5080,7 +5124,7 @@ void *new_sock_channel(Socket s) void ssh_unthrottle(int bufsize) { if (ssh_version == 1) { - if (bufsize < SSH1_BUFFER_LIMIT) { + if (ssh1_stdout_throttling && bufsize < SSH1_BUFFER_LIMIT) { ssh1_stdout_throttling = 0; ssh1_throttle(-1); }