X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/7e4a33c57c8726c23cb043ab0858de34cfd7c048..bd0b4caf4402bb428a6c13af8f1fc02a22f43aec:/ssh.c diff --git a/ssh.c b/ssh.c index 77bb4594..292fb8b1 100644 --- a/ssh.c +++ b/ssh.c @@ -827,6 +827,12 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen) st->biglen = st->len + st->pad; ssh->pktin.length = st->len - 5; + if (st->biglen < 0) { + bombout(("Extremely large packet length from server suggests" + " data stream corruption")); + crStop(0); + } + if (ssh->pktin.maxlen < st->biglen) { ssh->pktin.maxlen = st->biglen; ssh->pktin.data = sresize(ssh->pktin.data, st->biglen + APIEXTRA, @@ -1822,7 +1828,7 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) (!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, "OSU_1.4alpha3")))) { + !strcmp(imp, "OSU_1.4alpha3") || !strcmp(imp, "OSU_1.5alpha4")))) { /* * These versions don't support SSH1_MSG_IGNORE, so we have * to use a different defence against password length @@ -2435,7 +2441,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (!ssh1_pkt_getrsakey(ssh, &servkey, &s->keystr1) || !ssh1_pkt_getrsakey(ssh, &hostkey, &s->keystr2)) { - bombout(("SSH1 public key packet stopped before public keys")); + bombout(("Failed to read SSH1 public keys from public key packet")); crStop(0); } @@ -3443,27 +3449,40 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) } } if (sport && dport) { + /* Set up a description of the source port. */ + char *sportdesc = dupprintf("%.*s%.*s%.*s%.*s%d%.*s", + (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL, + (int)(*saddr?1:0), ":", + (int)(sserv ? strlen(sports) : 0), sports, + sserv, "(", sport, sserv, ")"); if (type == 'L') { - pfd_addforward(host, dport, *saddr ? saddr : NULL, - sport, ssh, &ssh->cfg); - logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s" - " forwarding to %s:%.*s%.*s%d%.*s", - (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL, - (int)(*saddr?1:0), ":", - (int)(sserv ? strlen(sports) : 0), sports, - sserv, "(", sport, sserv, ")", - host, - (int)(dserv ? strlen(dports) : 0), dports, - dserv, "(", dport, dserv, ")"); + /* Verbose description of the destination port */ + char *dportdesc = dupprintf("%s:%.*s%.*s%d%.*s", + host, + (int)(dserv ? strlen(dports) : 0), dports, + dserv, "(", dport, dserv, ")"); + const char *err = pfd_addforward(host, dport, + *saddr ? saddr : NULL, + sport, ssh, &ssh->cfg); + if (err) { + logeventf(ssh, "Local port %s forward to %s" + " failed: %s", sportdesc, dportdesc, err); + } else { + logeventf(ssh, "Local port %s forwarding to %s", + sportdesc, dportdesc); + } + sfree(dportdesc); } else if (type == 'D') { - pfd_addforward(NULL, -1, *saddr ? saddr : NULL, - sport, ssh, &ssh->cfg); - logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s" - " doing SOCKS dynamic forwarding", - (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL, - (int)(*saddr?1:0), ":", - (int)(sserv ? strlen(sports) : 0), sports, - sserv, "(", sport, sserv, ")"); + const char *err = pfd_addforward(NULL, -1, + *saddr ? saddr : NULL, + sport, ssh, &ssh->cfg); + if (err) { + logeventf(ssh, "Local port %s SOCKS dynamic forward" + " setup failed: %s", sportdesc, err); + } else { + logeventf(ssh, "Local port %s doing SOCKS" + " dynamic forwarding", sportdesc); + } } else { struct ssh_rportfwd *pf; pf = snew(struct ssh_rportfwd); @@ -3506,6 +3525,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) logevent("Remote port forwarding enabled"); } } + sfree(sportdesc); } } } @@ -4130,21 +4150,25 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) } /* List client->server compression algorithms. */ ssh2_pkt_addstring_start(ssh); - for (i = 0; i < lenof(compressions) + 1; i++) { - const struct ssh_compress *c = - i == 0 ? s->preferred_comp : compressions[i - 1]; - ssh2_pkt_addstring_str(ssh, c->name); - if (i < lenof(compressions)) + assert(lenof(compressions) > 1); + ssh2_pkt_addstring_str(ssh, s->preferred_comp->name); + for (i = 0; i < lenof(compressions); i++) { + const struct ssh_compress *c = compressions[i]; + if (c != s->preferred_comp) { ssh2_pkt_addstring_str(ssh, ","); + ssh2_pkt_addstring_str(ssh, c->name); + } } /* List server->client compression algorithms. */ ssh2_pkt_addstring_start(ssh); - for (i = 0; i < lenof(compressions) + 1; i++) { - const struct ssh_compress *c = - i == 0 ? s->preferred_comp : compressions[i - 1]; - ssh2_pkt_addstring_str(ssh, c->name); - if (i < lenof(compressions)) + assert(lenof(compressions) > 1); + ssh2_pkt_addstring_str(ssh, s->preferred_comp->name); + for (i = 0; i < lenof(compressions); i++) { + const struct ssh_compress *c = compressions[i]; + if (c != s->preferred_comp) { ssh2_pkt_addstring_str(ssh, ","); + ssh2_pkt_addstring_str(ssh, c->name); + } } /* List client->server languages. Empty list. */ ssh2_pkt_addstring_start(ssh); @@ -4610,7 +4634,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) int num_prompts, curr_prompt, echo; char username[100]; int got_username; - char pwprompt[200]; + char pwprompt[512]; char password[100]; void *publickey_blob; int publickey_bloblen; @@ -5189,9 +5213,16 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh_pkt_getstring(ssh, &prompt, &prompt_len); if (prompt_len > 0) { - strncpy(s->pwprompt, prompt, sizeof(s->pwprompt)); - s->pwprompt[prompt_len < sizeof(s->pwprompt) ? - prompt_len : sizeof(s->pwprompt)-1] = '\0'; + static const char trunc[] = ": "; + static const int prlen = sizeof(s->pwprompt) - + lenof(trunc); + if (prompt_len > prlen) { + memcpy(s->pwprompt, prompt, prlen); + strcpy(s->pwprompt + prlen, trunc); + } else { + memcpy(s->pwprompt, prompt, prompt_len); + s->pwprompt[prompt_len] = '\0'; + } } else { strcpy(s->pwprompt, ": "); @@ -5589,27 +5620,40 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) } } if (sport && dport) { + /* Set up a description of the source port. */ + char *sportdesc = dupprintf("%.*s%.*s%.*s%.*s%d%.*s", + (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL, + (int)(*saddr?1:0), ":", + (int)(sserv ? strlen(sports) : 0), sports, + sserv, "(", sport, sserv, ")"); if (type == 'L') { - pfd_addforward(host, dport, *saddr ? saddr : NULL, - sport, ssh, &ssh->cfg); - logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s" - " forwarding to %s:%.*s%.*s%d%.*s", - (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL, - (int)(*saddr?1:0), ":", - (int)(sserv ? strlen(sports) : 0), sports, - sserv, "(", sport, sserv, ")", - host, - (int)(dserv ? strlen(dports) : 0), dports, - dserv, "(", dport, dserv, ")"); + /* Verbose description of the destination port */ + char *dportdesc = dupprintf("%s:%.*s%.*s%d%.*s", + host, + (int)(dserv ? strlen(dports) : 0), dports, + dserv, "(", dport, dserv, ")"); + const char *err = pfd_addforward(host, dport, + *saddr ? saddr : NULL, + sport, ssh, &ssh->cfg); + if (err) { + logeventf(ssh, "Local port %s forward to %s" + " failed: %s", sportdesc, dportdesc, err); + } else { + logeventf(ssh, "Local port %s forwarding to %s", + sportdesc, dportdesc); + } + sfree(dportdesc); } else if (type == 'D') { - pfd_addforward(NULL, -1, *saddr ? saddr : NULL, - sport, ssh, &ssh->cfg); - logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s" - " doing SOCKS dynamic forwarding", - (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL, - (int)(*saddr?1:0), ":", - (int)(sserv ? strlen(sports) : 0), sports, - sserv, "(", sport, sserv, ")"); + const char *err = pfd_addforward(NULL, -1, + *saddr ? saddr : NULL, + sport, ssh, &ssh->cfg); + if (err) { + logeventf(ssh, "Local port %s SOCKS dynamic forward" + " setup failed: %s", sportdesc, err); + } else { + logeventf(ssh, "Local port %s doing SOCKS" + " dynamic forwarding", sportdesc); + } } else { struct ssh_rportfwd *pf; pf = snew(struct ssh_rportfwd); @@ -5621,14 +5665,9 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) " to %s:%d", host, dport); sfree(pf); } else { - logeventf(ssh, "Requesting remote port " - "%.*s%.*s%.*s%.*s%d%.*s" + logeventf(ssh, "Requesting remote port %s" " forward to %s:%.*s%.*s%d%.*s", - (int)(*saddr?strlen(saddr):0), - *saddr?saddr:NULL, - (int)(*saddr?1:0), ":", - (int)(sserv ? strlen(sports) : 0), sports, - sserv, "(", sport, sserv, ")", + sportdesc, host, (int)(dserv ? strlen(dports) : 0), dports, dserv, "(", dport, dserv, ")"); @@ -5669,6 +5708,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) } } } + sfree(sportdesc); } } }