X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/36b8d9bb9274b5ca088063a83d255121691a579f..e35fb54b2ce23c668414c0f5cd072c709374fc6d:/ssh.c diff --git a/ssh.c b/ssh.c index f06b2df2..ea008dd4 100644 --- a/ssh.c +++ b/ssh.c @@ -1780,7 +1780,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) (ssh->cfg.sshbug_ignore1 == AUTO && (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") || !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") || - !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25")))) { + !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25") || + !strcmp(imp, "OSU_1.4alpha3")))) { /* * These versions don't support SSH1_MSG_IGNORE, so we have * to use a different defence against password length @@ -1792,7 +1793,7 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) if (ssh->cfg.sshbug_plainpw1 == FORCE_ON || (ssh->cfg.sshbug_plainpw1 == AUTO && - (!strcmp(imp, "Cisco-1.25")))) { + (!strcmp(imp, "Cisco-1.25") || !strcmp(imp, "OSU_1.4alpha3")))) { /* * These versions need a plain password sent; they can't * handle having a null and a random length of data after @@ -2168,7 +2169,6 @@ static const char *connect_to_host(Ssh ssh, char *host, int port, ssh->fn = &fn_table; ssh->s = new_connection(addr, *realhost, port, 0, 1, nodelay, (Plug) ssh, &ssh->cfg); - sk_addr_free(addr); if ((err = sk_socket_error(ssh->s)) != NULL) { ssh->s = NULL; return err; @@ -2535,6 +2535,22 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh->crcda_ctx = crcda_make_context(); logevent("Installing CRC compensation attack detector"); + if (servkey.modulus) { + sfree(servkey.modulus); + servkey.modulus = NULL; + } + if (servkey.exponent) { + sfree(servkey.exponent); + servkey.exponent = NULL; + } + if (hostkey.modulus) { + sfree(hostkey.modulus); + hostkey.modulus = NULL; + } + if (hostkey.exponent) { + sfree(hostkey.exponent); + hostkey.exponent = NULL; + } crWaitUntil(ispkt); if (ssh->pktin.type != SSH1_SMSG_SUCCESS) { @@ -2602,7 +2618,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* Load the public half of ssh->cfg.keyfile so we notice if it's in Pageant */ if (!filename_is_null(ssh->cfg.keyfile)) { if (!rsakey_pubblob(&ssh->cfg.keyfile, - &s->publickey_blob, &s->publickey_bloblen)) + &s->publickey_blob, &s->publickey_bloblen, NULL)) s->publickey_blob = NULL; } else s->publickey_blob = NULL; @@ -2751,6 +2767,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (s->authed) break; } + sfree(s->response); } if (s->authed) break; @@ -2888,11 +2905,15 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->tried_publickey = 1; { - int ret = loadrsakey(&ssh->cfg.keyfile, &s->key, s->password); + const char *error = NULL; + int ret = loadrsakey(&ssh->cfg.keyfile, &s->key, s->password, + &error); if (ret == 0) { c_write_str(ssh, "Couldn't load private key from "); c_write_str(ssh, filename_to_str(&ssh->cfg.keyfile)); - c_write_str(ssh, ".\r\n"); + c_write_str(ssh, " ("); + c_write_str(ssh, error); + c_write_str(ssh, ").\r\n"); continue; /* go and try password */ } if (ret == -1) { @@ -3033,6 +3054,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) } logevent("Sending password with camouflage packets"); ssh_pkt_defersend(ssh); + sfree(randomstr); } else if (!(ssh->remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) { /* @@ -3298,6 +3320,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) } else { while (*ssh->portfwd_strptr) ssh->portfwd_strptr++; dport = dserv = -1; + ssh->portfwd_strptr++; /* eat the NUL and move to next one */ } sport = atoi(sports); sserv = 0; @@ -3378,11 +3401,19 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) } if (!ssh->cfg.nopty) { + /* Unpick the terminal-speed string. */ + /* XXX perhaps we should allow no speeds to be sent. */ + int ospeed = 38400, ispeed = 38400; /* last-resort defaults */ + sscanf(ssh->cfg.termspeed, "%d,%d", &ospeed, &ispeed); + /* Send the pty request. */ send_packet(ssh, SSH1_CMSG_REQUEST_PTY, PKT_STR, ssh->cfg.termtype, PKT_INT, ssh->term_height, PKT_INT, ssh->term_width, - PKT_INT, 0, PKT_INT, 0, PKT_CHAR, 0, PKT_END); + PKT_INT, 0, PKT_INT, 0, /* width,height in pixels */ + PKT_CHAR, 192, PKT_INT, ispeed, /* TTY_OP_ISPEED */ + PKT_CHAR, 193, PKT_INT, ospeed, /* TTY_OP_OSPEED */ + PKT_CHAR, 0, PKT_END); ssh->state = SSH_STATE_INTERMED; do { crReturnV; @@ -3395,7 +3426,8 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) c_write_str(ssh, "Server refused to allocate pty\r\n"); ssh->editing = ssh->echoing = 1; } - logevent("Allocated pty"); + logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)", + ospeed, ispeed); } else { ssh->editing = ssh->echoing = 1; } @@ -4333,6 +4365,12 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (ssh->sccomp->text_name) logeventf(ssh, "Initialised %s decompression", ssh->sccomp->text_name); + freebn(s->f); + freebn(s->K); + if (ssh->kex == &ssh_diffiehellman_gex) { + freebn(s->g); + freebn(s->p); + } /* * If this is the first key exchange phase, we must pass the @@ -4586,7 +4624,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (keytype == SSH_KEYTYPE_SSH2) { s->publickey_blob = ssh2_userkey_loadpub(&ssh->cfg.keyfile, NULL, - &s->publickey_bloblen); + &s->publickey_bloblen, NULL); } else { char *msgbuf; logeventf(ssh, "Unable to use this key file (%s)", @@ -4715,6 +4753,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->method = 0; ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK; + s->need_pw = FALSE; /* * Most password/passphrase prompts will be @@ -4894,6 +4933,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (s->authed) continue; } + sfree(s->response); } if (!s->method && s->can_pubkey && s->publickey_blob @@ -4916,7 +4956,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) pub_blob = (unsigned char *)ssh2_userkey_loadpub(&ssh->cfg.keyfile, &algorithm, - &pub_blob_len); + &pub_blob_len, + NULL); if (pub_blob) { ssh2_pkt_init(ssh, SSH2_MSG_USERAUTH_REQUEST); ssh2_pkt_addstring(ssh, s->username); @@ -5093,14 +5134,18 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) * We have our passphrase. Now try the actual authentication. */ struct ssh2_userkey *key; + const char *error = NULL; - key = ssh2_load_userkey(&ssh->cfg.keyfile, s->password); + key = ssh2_load_userkey(&ssh->cfg.keyfile, s->password, + &error); if (key == SSH2_WRONG_PASSPHRASE || key == NULL) { if (key == SSH2_WRONG_PASSPHRASE) { c_write_str(ssh, "Wrong passphrase\r\n"); s->tried_pubkey_config = FALSE; } else { - c_write_str(ssh, "Unable to load private key\r\n"); + c_write_str(ssh, "Unable to load private key ("); + c_write_str(ssh, error); + c_write_str(ssh, ")\r\n"); s->tried_pubkey_config = TRUE; } /* Send a spurious AUTH_NONE to return to the top. */ @@ -5162,6 +5207,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh2_pkt_send(ssh); s->type = AUTH_TYPE_PUBLICKEY; + key->alg->freekey(key->data); } } else if (s->method == AUTH_PASSWORD) { /* @@ -5409,6 +5455,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) } else { while (*ssh->portfwd_strptr) ssh->portfwd_strptr++; dport = dserv = -1; + ssh->portfwd_strptr++; /* eat the NUL and move to next one */ } sport = atoi(sports); sserv = 0; @@ -5545,6 +5592,11 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) * Now allocate a pty for the session. */ if (!ssh->cfg.nopty) { + /* Unpick the terminal-speed string. */ + /* XXX perhaps we should allow no speeds to be sent. */ + int ospeed = 38400, ispeed = 38400; /* last-resort defaults */ + sscanf(ssh->cfg.termspeed, "%d,%d", &ospeed, &ispeed); + /* Build the pty request. */ ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST); ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid); /* recipient channel */ ssh2_pkt_addstring(ssh, "pty-req"); @@ -5555,7 +5607,11 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh2_pkt_adduint32(ssh, 0); /* pixel width */ ssh2_pkt_adduint32(ssh, 0); /* pixel height */ ssh2_pkt_addstring_start(ssh); - ssh2_pkt_addstring_data(ssh, "\0", 1); /* TTY_OP_END, no special options */ + ssh2_pkt_addbyte(ssh, 128); /* TTY_OP_ISPEED */ + ssh2_pkt_adduint32(ssh, ispeed); + ssh2_pkt_addbyte(ssh, 129); /* TTY_OP_OSPEED */ + ssh2_pkt_adduint32(ssh, ospeed); + ssh2_pkt_addstring_data(ssh, "\0", 1); /* TTY_OP_END */ ssh2_pkt_send(ssh); ssh->state = SSH_STATE_INTERMED; @@ -5580,7 +5636,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) c_write_str(ssh, "Server refused to allocate pty\r\n"); ssh->editing = ssh->echoing = 1; } else { - logevent("Allocated pty"); + logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)", + ospeed, ispeed); } } else { ssh->editing = ssh->echoing = 1; @@ -6230,10 +6287,18 @@ static void ssh_free(void *handle) ssh->csmac->free_context(ssh->cs_mac_ctx); if (ssh->sc_mac_ctx) ssh->scmac->free_context(ssh->sc_mac_ctx); - if (ssh->cs_comp_ctx) - ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx); - if (ssh->sc_comp_ctx) - ssh->sccomp->compress_cleanup(ssh->sc_comp_ctx); + if (ssh->cs_comp_ctx) { + if (ssh->cscomp) + ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx); + else + zlib_compress_cleanup(ssh->cs_comp_ctx); + } + if (ssh->sc_comp_ctx) { + if (ssh->sccomp) + ssh->sccomp->decompress_cleanup(ssh->sc_comp_ctx); + else + zlib_decompress_cleanup(ssh->sc_comp_ctx); + } if (ssh->kex_ctx) dh_cleanup(ssh->kex_ctx); sfree(ssh->savedhost); @@ -6267,7 +6332,22 @@ static void ssh_free(void *handle) sfree(ssh->do_ssh1_login_state); sfree(ssh->do_ssh2_transport_state); sfree(ssh->do_ssh2_authconn_state); - + if (ssh->pktout.data) { + sfree(ssh->pktout.data); + ssh->pktout.data = NULL; + } + if (ssh->pktin.data) { + sfree(ssh->pktin.data); + ssh->pktin.data = NULL; + } + if (ssh->crcda_ctx) { + crcda_free_context(ssh->crcda_ctx); + ssh->crcda_ctx = NULL; + } + if (ssh->logctx) { + log_free(ssh->logctx); + ssh->logctx = NULL; + } if (ssh->s) ssh_do_close(ssh); sfree(ssh);