X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/af659722d3fc952ddf101eb18aea60bef4acf3b5..bf5240cd14b02906921ef2e8ae9273bf44169299:/ssh.c diff --git a/ssh.c b/ssh.c index 36db4e75..27b7216d 100644 --- a/ssh.c +++ b/ssh.c @@ -725,6 +725,8 @@ static int ssh1_rdpkt(unsigned char **data, int *datalen) memcpy(buf + nowlen, pktin.body + 4, msglen); buf[nowlen + msglen] = '\0'; logevent(buf); + bombout(("Server sent disconnect message:\n\"%s\"", buf+nowlen)); + crReturn(0); } crFinish(0); @@ -898,6 +900,12 @@ static int ssh2_rdpkt(unsigned char **data, int *datalen) memcpy(buf + nowlen, pktin.data + 14, msglen); buf[nowlen + msglen] = '\0'; logevent(buf); + bombout(("Server sent disconnect message\ntype %d (%s):\n\"%s\"", + reason, + (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ? + ssh2_disconnect_reasons[reason] : "unknown", + buf+nowlen)); + crReturn(0); } crFinish(0); @@ -1594,6 +1602,9 @@ static void ssh_gotdata(unsigned char *data, int datalen) while (1) { while (datalen > 0) { if (s_rdpkt(&data, &datalen) == 0) { + if (ssh_state == SSH_STATE_CLOSED) { + return; + } ssh_protocol(NULL, 0, 1); if (ssh_state == SSH_STATE_CLOSED) { return; @@ -1686,6 +1697,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 +1713,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; @@ -1777,6 +1799,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) struct MD5Context md5c; static unsigned long supported_ciphers_mask, supported_auths_mask; static int tried_publickey; + static int tis_auth_refused, ccard_auth_refused; static unsigned char session_id[16]; static int cipher_type; static char username[100]; @@ -2025,6 +2048,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) crWaitUntil(ispkt); tried_publickey = 0; + tis_auth_refused = ccard_auth_refused = 0; while (pktin.type == SSH1_SMSG_FAILURE) { static char password[100]; @@ -2032,12 +2056,8 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) static int pos; static char c; static int pwpkt_type; - /* - * Show password prompt, having first obtained it via a TIS - * or CryptoCard exchange if we're doing TIS or CryptoCard - * authentication. - */ pwpkt_type = SSH1_CMSG_AUTH_PASSWORD; + if (agent_exists()) { /* * Attempt RSA authentication using Pageant. @@ -2160,9 +2180,9 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) if (*cfg.keyfile && !tried_publickey) pwpkt_type = SSH1_CMSG_AUTH_RSA; - if (pktin.type == SSH1_SMSG_FAILURE && - cfg.try_tis_auth && - (supported_auths_mask & (1 << SSH1_AUTH_TIS))) { + if (cfg.try_tis_auth && + (supported_auths_mask & (1 << SSH1_AUTH_TIS)) && + !tis_auth_refused) { pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE; logevent("Requested TIS authentication"); send_packet(SSH1_CMSG_AUTH_TIS, PKT_END); @@ -2171,6 +2191,8 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) logevent("TIS authentication declined"); if (flags & FLAG_INTERACTIVE) c_write_str("TIS authentication refused.\r\n"); + tis_auth_refused = 1; + continue; } else { int challengelen = ((pktin.body[0] << 24) | (pktin.body[1] << 16) | @@ -2180,12 +2202,17 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) if (challengelen > sizeof(prompt) - 1) challengelen = sizeof(prompt) - 1; /* prevent overrun */ memcpy(prompt, pktin.body + 4, challengelen); - prompt[challengelen] = '\0'; + /* Prompt heuristic comes from OpenSSH */ + strncpy(prompt + challengelen, + memchr(prompt, '\n', challengelen) ? + "": "\r\nResponse: ", + (sizeof prompt) - challengelen); + prompt[(sizeof prompt) - 1] = '\0'; } } - if (pktin.type == SSH1_SMSG_FAILURE && - cfg.try_tis_auth && - (supported_auths_mask & (1 << SSH1_AUTH_CCARD))) { + if (cfg.try_tis_auth && + (supported_auths_mask & (1 << SSH1_AUTH_CCARD)) && + !ccard_auth_refused) { pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE; logevent("Requested CryptoCard authentication"); send_packet(SSH1_CMSG_AUTH_CCARD, PKT_END); @@ -2193,6 +2220,8 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) if (pktin.type != SSH1_SMSG_AUTH_CCARD_CHALLENGE) { logevent("CryptoCard authentication declined"); c_write_str("CryptoCard authentication refused.\r\n"); + ccard_auth_refused = 1; + continue; } else { int challengelen = ((pktin.body[0] << 24) | (pktin.body[1] << 16) | @@ -2202,7 +2231,9 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) if (challengelen > sizeof(prompt) - 1) challengelen = sizeof(prompt) - 1; /* prevent overrun */ memcpy(prompt, pktin.body + 4, challengelen); - strncpy(prompt + challengelen, "\r\nResponse : ", + strncpy(prompt + challengelen, + memchr(prompt, '\n', challengelen) ? + "" : "\r\nResponse: ", sizeof(prompt) - challengelen); prompt[sizeof(prompt) - 1] = '\0'; } @@ -2224,6 +2255,11 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) sfree(comment); } + /* + * Show password prompt, having first obtained it via a TIS + * or CryptoCard exchange if we're doing TIS or CryptoCard + * authentication. + */ if (ssh_get_line) { if (!ssh_get_line(prompt, password, sizeof(password), TRUE)) { /* @@ -2239,7 +2275,9 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) crReturn(1); } } else { - c_write_str(prompt); + /* Prompt may have come from server. We've munged it a bit, so + * we know it to be zero-terminated at least once. */ + c_write_untrusted(prompt, strlen(prompt)); pos = 0; ssh_send_ok = 1; while (pos >= 0) { @@ -2288,7 +2326,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) tried_publickey = 1; i = loadrsakey(cfg.keyfile, &pubkey, password); if (i == 0) { - c_write_str("Couldn't load public key from "); + c_write_str("Couldn't load private key from "); c_write_str(cfg.keyfile); c_write_str(".\r\n"); continue; /* go and try password */ @@ -2709,7 +2747,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); } @@ -2955,7 +2993,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); } @@ -5113,7 +5151,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); }