X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/57476f6b080ede65f7b92a4d2b1dd2c2da996fa3..22b26f2487d08d6d98f0ce3a75c10c7097264493:/ssh.c diff --git a/ssh.c b/ssh.c index 6072e7b4..26cfbaa4 100644 --- a/ssh.c +++ b/ssh.c @@ -263,6 +263,13 @@ static struct rdpkt1_state_tag { int chunk; } rdpkt1_state; +static struct rdpkt2_state_tag { + long len, pad, payload, packetlen, maclen; + int i; + int cipherblk; + unsigned long incoming_sequence; +} rdpkt2_state; + static int ssh_channelcmp(void *av, void *bv) { struct ssh_channel *a = (struct ssh_channel *)av; struct ssh_channel *b = (struct ssh_channel *)bv; @@ -425,29 +432,24 @@ next_packet: static int ssh2_rdpkt(unsigned char **data, int *datalen) { - static long len, pad, payload, packetlen, maclen; - static int i; - static int cipherblk; - static unsigned long incoming_sequence = 0; + struct rdpkt2_state_tag *st = &rdpkt2_state; crBegin; next_packet: - pktin.type = 0; pktin.length = 0; - - if (cipher) - cipherblk = cipher->blksize; + if (sccipher) + st->cipherblk = sccipher->blksize; else - cipherblk = 8; - if (cipherblk < 8) - cipherblk = 8; - - if (pktin.maxlen < cipherblk) { - pktin.maxlen = cipherblk; - pktin.data = (pktin.data == NULL ? malloc(cipherblk+APIEXTRA) : - realloc(pktin.data, cipherblk+APIEXTRA)); + st->cipherblk = 8; + if (st->cipherblk < 8) + st->cipherblk = 8; + + if (pktin.maxlen < st->cipherblk) { + pktin.maxlen = st->cipherblk; + pktin.data = (pktin.data == NULL ? malloc(st->cipherblk+APIEXTRA) : + realloc(pktin.data, st->cipherblk+APIEXTRA)); if (!pktin.data) fatalbox("Out of memory"); } @@ -456,10 +458,10 @@ next_packet: * Acquire and decrypt the first block of the packet. This will * contain the length and padding details. */ - for (i = len = 0; i < cipherblk; i++) { + for (st->i = st->len = 0; st->i < st->cipherblk; st->i++) { while ((*datalen) == 0) - crReturn(cipherblk-i); - pktin.data[i] = *(*data)++; + crReturn(st->cipherblk-st->i); + pktin.data[st->i] = *(*data)++; (*datalen)--; } #ifdef FWHACK @@ -468,32 +470,32 @@ next_packet: } #endif if (sccipher) - sccipher->decrypt(pktin.data, cipherblk); + sccipher->decrypt(pktin.data, st->cipherblk); /* * Now get the length and padding figures. */ - len = GET_32BIT(pktin.data); - pad = pktin.data[4]; + st->len = GET_32BIT(pktin.data); + st->pad = pktin.data[4]; /* * This enables us to deduce the payload length. */ - payload = len - pad - 1; + st->payload = st->len - st->pad - 1; - pktin.length = payload + 5; + pktin.length = st->payload + 5; /* * So now we can work out the total packet length. */ - packetlen = len + 4; - maclen = scmac ? scmac->len : 0; + st->packetlen = st->len + 4; + st->maclen = scmac ? scmac->len : 0; /* * Adjust memory allocation if packet is too big. */ - if (pktin.maxlen < packetlen+maclen) { - pktin.maxlen = packetlen+maclen; + if (pktin.maxlen < st->packetlen+st->maclen) { + pktin.maxlen = st->packetlen+st->maclen; pktin.data = (pktin.data == NULL ? malloc(pktin.maxlen+APIEXTRA) : realloc(pktin.data, pktin.maxlen+APIEXTRA)); if (!pktin.data) @@ -503,31 +505,32 @@ next_packet: /* * Read and decrypt the remainder of the packet. */ - for (i = cipherblk; i < packetlen + maclen; i++) { + for (st->i = st->cipherblk; st->i < st->packetlen + st->maclen; st->i++) { while ((*datalen) == 0) - crReturn(packetlen + maclen - i); - pktin.data[i] = *(*data)++; + crReturn(st->packetlen + st->maclen - st->i); + pktin.data[st->i] = *(*data)++; (*datalen)--; } /* Decrypt everything _except_ the MAC. */ if (sccipher) - sccipher->decrypt(pktin.data + cipherblk, packetlen - cipherblk); + sccipher->decrypt(pktin.data + st->cipherblk, + st->packetlen - st->cipherblk); #if 0 - debug(("Got packet len=%d pad=%d\r\n", len, pad)); - for (i = 0; i < packetlen; i++) - debug((" %02x", (unsigned char)pktin.data[i])); + debug(("Got packet len=%d pad=%d\r\n", st->len, st->pad)); + for (st->i = 0; st->i < st->packetlen; st->i++) + debug((" %02x", (unsigned char)pktin.data[st->i])); debug(("\r\n")); #endif /* * Check the MAC. */ - if (scmac && !scmac->verify(pktin.data, len+4, incoming_sequence)) { + if (scmac && !scmac->verify(pktin.data, st->len+4, st->incoming_sequence)) { bombout(("Incorrect MAC received on packet")); crReturn(0); } - incoming_sequence++; /* whether or not we MACed */ + st->incoming_sequence++; /* whether or not we MACed */ pktin.savedpos = 6; pktin.type = pktin.data[5]; @@ -1028,6 +1031,8 @@ static int do_ssh_init(void) { break; } + rdpkt2_state.incoming_sequence = 0; + *vsp = 0; sprintf(vlog, "Server version: %s", vstring); vlog[strcspn(vlog, "\r\n")] = '\0'; @@ -1089,6 +1094,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) static int tried_publickey; static unsigned char session_id[16]; int cipher_type; + static char username[100]; crBegin; @@ -1212,7 +1218,6 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) fflush(stdout); { - static char username[100]; static int pos = 0; static char c; if ((flags & FLAG_INTERACTIVE) && !*cfg.username) { @@ -1440,7 +1445,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) } if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD) { sprintf(prompt, "%.90s@%.90s's password: ", - cfg.username, savedhost); + username, savedhost); } if (pwpkt_type == SSH1_CMSG_AUTH_RSA) { char *comment = NULL; @@ -1455,7 +1460,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) free(comment); } - if (!(flags & FLAG_INTERACTIVE)) { + if (ssh_get_password) { if (!ssh_get_password(prompt, password, sizeof(password))) { /* * get_password failed to get a password (for @@ -1876,18 +1881,18 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt) } /* List client->server encryption algorithms. */ ssh2_pkt_addstring_start(); - for (i = -1; i < lenof(ciphers); i++) { - const struct ssh_cipher *c = i<0 ? preferred_cipher : ciphers[i]; + for (i = 0; i < lenof(ciphers)+1; i++) { + const struct ssh_cipher *c = i==0 ? preferred_cipher : ciphers[i-1]; ssh2_pkt_addstring_str(c->name); - if (i < lenof(ciphers)-1) + if (i < lenof(ciphers)) ssh2_pkt_addstring_str(","); } /* List server->client encryption algorithms. */ ssh2_pkt_addstring_start(); - for (i = -1; i < lenof(ciphers); i++) { - const struct ssh_cipher *c = i<0 ? preferred_cipher : ciphers[i]; + for (i = 0; i < lenof(ciphers)+1; i++) { + const struct ssh_cipher *c = i==0 ? preferred_cipher : ciphers[i-1]; ssh2_pkt_addstring_str(c->name); - if (i < lenof(ciphers)-1) + if (i < lenof(ciphers)) ssh2_pkt_addstring_str(","); } /* List client->server MAC algorithms. */ @@ -1958,18 +1963,18 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt) } } ssh2_pkt_getstring(&str, &len); /* client->server cipher */ - for (i = -1; i < lenof(ciphers); i++) { - const struct ssh_cipher *c = i<0 ? preferred_cipher : ciphers[i]; + for (i = 0; i < lenof(ciphers)+1; i++) { + const struct ssh_cipher *c = i==0 ? preferred_cipher : ciphers[i-1]; if (in_commasep_string(c->name, str, len)) { - cscipher_tobe = ciphers[i]; + cscipher_tobe = c; break; } } ssh2_pkt_getstring(&str, &len); /* server->client cipher */ - for (i = -1; i < lenof(ciphers); i++) { - const struct ssh_cipher *c = i<0 ? preferred_cipher : ciphers[i]; + for (i = 0; i < lenof(ciphers)+1; i++) { + const struct ssh_cipher *c = i==0 ? preferred_cipher : ciphers[i-1]; if (in_commasep_string(c->name, str, len)) { - sccipher_tobe = ciphers[i]; + sccipher_tobe = c; break; } } @@ -2193,9 +2198,9 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) } } - if (!(flags & FLAG_INTERACTIVE)) { + if (ssh_get_password) { char prompt[200]; - sprintf(prompt, "%.90s@%.90s's password: ", cfg.username, savedhost); + sprintf(prompt, "%.90s@%.90s's password: ", username, savedhost); if (!ssh_get_password(prompt, password, sizeof(password))) { /* * get_password failed to get a password (for @@ -2622,5 +2627,6 @@ Backend ssh_backend = { ssh_size, ssh_special, ssh_socket, - ssh_sendok + ssh_sendok, + 22 };