X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/6571dbfd83b885249e7783dd381146c4bbc6fdaf..b7a189f38294c745ae4ea6efb55891c8196e275b:/ssh.c diff --git a/ssh.c b/ssh.c index 75da932e..62f2a8e2 100644 --- a/ssh.c +++ b/ssh.c @@ -299,8 +299,8 @@ extern void x11_unthrottle(Socket s); extern void x11_override_throttle(Socket s, int enable); extern char *pfd_newconnect(Socket * s, char *hostname, int port, void *c); -extern char *pfd_addforward(char *desthost, int destport, int port, - void *backhandle); +extern char *pfd_addforward(char *desthost, int destport, char *srcaddr, + int port, void *backhandle); extern void pfd_close(Socket s); extern int pfd_send(Socket s, char *data, int len); extern void pfd_confirm(Socket s); @@ -638,20 +638,29 @@ struct ssh_tag { int (*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen); }; -#define logevent(s) { logevent(ssh->frontend, s); \ - if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \ - { fprintf(stderr, "%s\n", s); fflush(stderr); } } +#define logevent(s) do { \ + logevent(ssh->frontend, s); \ + if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) { \ + fprintf(stderr, "%s\n", s); \ + fflush(stderr); \ + } \ +} while (0) /* logevent, only printf-formatted. */ void logeventf(Ssh ssh, char *fmt, ...) { va_list ap; - char stuff[200]; + char *buf; va_start(ap, fmt); - vsprintf(stuff, fmt, ap); + buf = dupvprintf(fmt, ap); va_end(ap); - logevent(stuff); + logevent(buf); + if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) { + fprintf(stderr, "%s\n", buf); + fflush(stderr); + } + sfree(buf); } #define bombout(msg) ( ssh->state = SSH_STATE_CLOSED, \ @@ -1049,30 +1058,29 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen) case SSH2_MSG_DISCONNECT: { /* log reason code in disconnect message */ - char buf[256]; + char *buf; + int nowlen; int reason = GET_32BIT(ssh->pktin.data + 6); unsigned msglen = GET_32BIT(ssh->pktin.data + 10); - unsigned nowlen; + if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) { - sprintf(buf, "Received disconnect message (%s)", - ssh2_disconnect_reasons[reason]); + buf = dupprintf("Received disconnect message (%s)", + ssh2_disconnect_reasons[reason]); } else { - sprintf(buf, "Received disconnect message (unknown type %d)", - reason); + buf = dupprintf("Received disconnect message (unknown" + " type %d)", reason); } logevent(buf); - strcpy(buf, "Disconnection message text: "); - nowlen = strlen(buf); - if (msglen > sizeof(buf) - nowlen - 1) - msglen = sizeof(buf) - nowlen - 1; - memcpy(buf + nowlen, ssh->pktin.data + 14, msglen); - buf[nowlen + msglen] = '\0'; + sfree(buf); + buf = dupprintf("Disconnection message text: %n%.*s", + &nowlen, msglen, ssh->pktin.data + 14); logevent(buf); bombout((ssh,"Server sent disconnect message\ntype %d (%s):\n\"%s\"", reason, (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ? ssh2_disconnect_reasons[reason] : "unknown", buf+nowlen)); + sfree(buf); crReturn(0); } break; @@ -1253,7 +1261,7 @@ static void construct_packet(Ssh ssh, int pkttype, va_list ap1, va_list ap2) pktlen += 4; break; case PKT_CHAR: - (void) va_arg(ap1, char); + (void) va_arg(ap1, int); pktlen++; break; case PKT_DATA: @@ -1286,7 +1294,7 @@ static void construct_packet(Ssh ssh, int pkttype, va_list ap1, va_list ap2) p += 4; break; case PKT_CHAR: - argchar = va_arg(ap2, unsigned char); + argchar = (unsigned char) va_arg(ap2, int); *p = argchar; p++; break; @@ -1612,11 +1620,15 @@ static int ssh2_pkt_getbool(Ssh ssh) } static void ssh2_pkt_getstring(Ssh ssh, char **p, int *length) { + int len; *p = NULL; *length = 0; if (ssh->pktin.length - ssh->pktin.savedpos < 4) return; - *length = GET_32BIT(ssh->pktin.data + ssh->pktin.savedpos); + len = GET_32BIT(ssh->pktin.data + ssh->pktin.savedpos); + if (len < 0) + return; + *length = len; ssh->pktin.savedpos += 4; if (ssh->pktin.length - ssh->pktin.savedpos < *length) return; @@ -1764,9 +1776,9 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) if (cfg.sshbug_hmac2 == BUG_ON || (cfg.sshbug_hmac2 == BUG_AUTO && - (!strncmp(imp, "2.1.0", 5) || !strncmp(imp, "2.0.", 4) || - !strncmp(imp, "2.2.0", 5) || !strncmp(imp, "2.3.0", 5) || - !strncmp(imp, "2.1 ", 4)))) { + (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) || + wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) || + wc_match("2.1 *", imp)))) { /* * These versions have the HMAC bug. */ @@ -1776,7 +1788,7 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) if (cfg.sshbug_derivekey2 == BUG_ON || (cfg.sshbug_derivekey2 == BUG_AUTO && - (!strncmp(imp, "2.0.", 4)))) { + (wc_match("2.0.0*", imp) || wc_match("2.0.1[01]*", imp) ))) { /* * These versions have the key-derivation bug (failing to * include the literal shared secret in the hashes that @@ -1788,8 +1800,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) if (cfg.sshbug_rsapad2 == BUG_ON || (cfg.sshbug_rsapad2 == BUG_AUTO && - ((!strncmp(imp, "OpenSSH_2.", 10) && imp[10]>='5' && imp[10]<='9') || - (!strncmp(imp, "OpenSSH_3.", 10) && imp[10]>='0' && imp[10]<='2')))){ + (wc_match("OpenSSH_2.[5-9]*", imp) || + wc_match("OpenSSH_3.[0-2]*", imp)))) { /* * These versions have the SSH2 RSA padding bug. */ @@ -1799,7 +1811,7 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) if (cfg.sshbug_dhgex2 == BUG_ON) { /* - * These versions have the SSH2 DH GEX bug. + * User specified the SSH2 DH GEX bug. */ ssh->remote_bugs |= BUG_SSH2_DH_GEX; logevent("We believe remote version has SSH2 DH group exchange bug"); @@ -2059,12 +2071,8 @@ static char *connect_to_host(Ssh ssh, char *host, int port, /* * Try to find host. */ - { - char buf[200]; - sprintf(buf, "Looking up host \"%.170s\"", host); - logevent(buf); - } - addr = sk_namelookup(host, realhost); + logeventf(ssh, "Looking up host \"%s\"", host); + addr = name_lookup(host, port, realhost); if ((err = sk_addr_error(addr))) return err; @@ -2072,10 +2080,9 @@ static char *connect_to_host(Ssh ssh, char *host, int port, * Open socket. */ { - char buf[200], addrbuf[100]; + char addrbuf[100]; sk_getaddr(addr, addrbuf, 100); - sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); - logevent(buf); + logeventf(ssh, "Connecting to %s port %d", addrbuf, port); } ssh->fn = &fn_table; ssh->s = new_connection(addr, *realhost, port, 0, 1, nodelay, (Plug) ssh); @@ -2396,11 +2403,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) &ssh_3des); ssh->v1_cipher_ctx = ssh->cipher->make_context(); ssh->cipher->sesskey(ssh->v1_cipher_ctx, ssh->session_key); - { - char buf[256]; - sprintf(buf, "Initialised %.200s encryption", ssh->cipher->text_name); - logevent(buf); - } + logeventf(ssh, "Initialised %s encryption", ssh->cipher->text_name); ssh->crcda_ctx = crcda_make_context(); logevent("Installing CRC compensation attack detector"); @@ -2664,8 +2667,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) char msgbuf[256]; if (flags & FLAG_VERBOSE) c_write_str(ssh, "Trying public key authentication.\r\n"); - sprintf(msgbuf, "Trying public key \"%.200s\"", cfg.keyfile); - logevent(msgbuf); + logeventf(ssh, "Trying public key \"%s\"", cfg.keyfile); type = key_type(cfg.keyfile); if (type != SSH_KEYTYPE_SSH1) { sprintf(msgbuf, "Key is of wrong type (%s)", @@ -3069,91 +3071,104 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) char type; int n; int sport,dport,sserv,dserv; - char sports[256], dports[256], host[256]; - char buf[1024]; - struct servent *se; + char sports[256], dports[256], saddr[256], host[256]; ssh->rportfwds = newtree234(ssh_rportcmp_ssh1); /* Add port forwardings. */ ssh->portfwd_strptr = cfg.portfwd; while (*ssh->portfwd_strptr) { type = *ssh->portfwd_strptr++; + saddr[0] = '\0'; n = 0; - while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != '\t') - sports[n++] = *ssh->portfwd_strptr++; + while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != '\t') { + if (*ssh->portfwd_strptr == ':') { + /* + * We've seen a colon in the middle of the + * source port number. This means that + * everything we've seen until now is the + * source _address_, so we'll move it into + * saddr and start sports from the beginning + * again. + */ + ssh->portfwd_strptr++; + sports[n] = '\0'; + strcpy(saddr, sports); + n = 0; + } + if (n < 255) sports[n++] = *ssh->portfwd_strptr++; + } sports[n] = 0; if (*ssh->portfwd_strptr == '\t') ssh->portfwd_strptr++; n = 0; - while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') - host[n++] = *ssh->portfwd_strptr++; + while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') { + if (n < 255) host[n++] = *ssh->portfwd_strptr++; + } host[n] = 0; if (*ssh->portfwd_strptr == ':') ssh->portfwd_strptr++; n = 0; - while (*ssh->portfwd_strptr) - dports[n++] = *ssh->portfwd_strptr++; + while (*ssh->portfwd_strptr) { + if (n < 255) dports[n++] = *ssh->portfwd_strptr++; + } dports[n] = 0; ssh->portfwd_strptr++; dport = atoi(dports); dserv = 0; if (dport == 0) { dserv = 1; - se = getservbyname(dports, NULL); - if (se != NULL) { - dport = ntohs(se->s_port); - } else { - sprintf(buf, - "Service lookup failed for destination port \"%s\"", - dports); - logevent(buf); + dport = net_service_lookup(dports); + if (!dport) { + logeventf(ssh, "Service lookup failed for" + " destination port \"%s\"", dports); } } sport = atoi(sports); sserv = 0; if (sport == 0) { sserv = 1; - se = getservbyname(sports, NULL); - if (se != NULL) { - sport = ntohs(se->s_port); - } else { - sprintf(buf, - "Service lookup failed for source port \"%s\"", - sports); - logevent(buf); + sport = net_service_lookup(sports); + if (!sport) { + logeventf(ssh, "Service lookup failed for source" + " port \"%s\"", sports); } } if (sport && dport) { if (type == 'L') { - pfd_addforward(host, dport, sport, ssh); - sprintf(buf, "Local port %.*s%.*s%d%.*s forwarding to" - " %s:%.*s%.*s%d%.*s", - sserv ? strlen(sports) : 0, sports, - sserv, "(", sport, sserv, ")", - host, - dserv ? strlen(dports) : 0, dports, - dserv, "(", dport, dserv, ")"); - logevent(buf); + pfd_addforward(host, dport, *saddr ? saddr : NULL, + sport, ssh); + 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, ")"); } else { struct ssh_rportfwd *pf; pf = smalloc(sizeof(*pf)); strcpy(pf->dhost, host); pf->dport = dport; + if (saddr) { + logeventf(ssh, + "SSH1 cannot handle source address spec \"%s:%d\"; ignoring", + saddr, sport); + } if (add234(ssh->rportfwds, pf) != pf) { - sprintf(buf, - "Duplicate remote port forwarding to %s:%d", - host, dport); - logevent(buf); + logeventf(ssh, + "Duplicate remote port forwarding to %s:%d", + host, dport); sfree(pf); } else { - sprintf(buf, "Requesting remote port %.*s%.*s%d%.*s" - " forward to %s:%.*s%.*s%d%.*s", - sserv ? strlen(sports) : 0, sports, - sserv, "(", sport, sserv, ")", - host, - dserv ? strlen(dports) : 0, dports, - dserv, "(", dport, dserv, ")"); - logevent(buf); + logeventf(ssh, "Requesting remote port %.*s%.*s%d%.*s" + " forward to %s:%.*s%.*s%d%.*s", + (int)(sserv ? strlen(sports) : 0), sports, + sserv, "(", sport, sserv, ")", + host, + (int)(dserv ? strlen(dports) : 0), dports, + dserv, "(", dport, dserv, ")"); send_packet(ssh, SSH1_CMSG_PORT_FORWARD_REQUEST, PKT_INT, sport, PKT_STR, host, @@ -3411,7 +3426,6 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) } else if (ssh->pktin.type == SSH1_MSG_CHANNEL_OPEN_FAILURE) { unsigned int remoteid = GET_32BIT(ssh->pktin.body); - unsigned int localid = GET_32BIT(ssh->pktin.body+4); struct ssh_channel *c; c = find234(ssh->channels, &remoteid, ssh_channelfind); @@ -3582,7 +3596,10 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) */ static int in_commasep_string(char *needle, char *haystack, int haylen) { - int needlen = strlen(needle); + int needlen; + if (!needle || !haystack) /* protect against null pointers */ + return 0; + needlen = strlen(needle); while (1) { /* * Is it at the start of the string? @@ -3817,7 +3834,8 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (!ispkt) crWaitUntil(ispkt); - sha_string(&ssh->exhash, ssh->pktin.data + 5, ssh->pktin.length - 5); + if (ssh->pktin.length > 5) + sha_string(&ssh->exhash, ssh->pktin.data + 5, ssh->pktin.length - 5); /* * Now examine the other side's KEXINIT to see what we're up @@ -3878,7 +3896,8 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) } } if (!s->cscipher_tobe) { - bombout((ssh,"Couldn't agree a client-to-server cipher (available: %s)", str)); + bombout((ssh,"Couldn't agree a client-to-server cipher (available: %s)", + str ? str : "(null)")); crReturn(0); } @@ -3903,7 +3922,8 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) } } if (!s->sccipher_tobe) { - bombout((ssh,"Couldn't agree a server-to-client cipher (available: %s)", str)); + bombout((ssh,"Couldn't agree a server-to-client cipher (available: %s)", + str ? str : "(null)")); crReturn(0); } @@ -4124,26 +4144,16 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'F',keyspace); ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace); } - { - char buf[256]; - sprintf(buf, "Initialised %.200s client->server encryption", - ssh->cscipher->text_name); - logevent(buf); - sprintf(buf, "Initialised %.200s server->client encryption", - ssh->sccipher->text_name); - logevent(buf); - if (ssh->cscomp->text_name) { - sprintf(buf, "Initialised %.200s compression", - ssh->cscomp->text_name); - logevent(buf); - } - if (ssh->sccomp->text_name) { - sprintf(buf, "Initialised %.200s decompression", - ssh->sccomp->text_name); - logevent(buf); - } - } - + logeventf(ssh, "Initialised %.200s client->server encryption", + ssh->cscipher->text_name); + logeventf(ssh, "Initialised %.200s server->client encryption", + ssh->sccipher->text_name); + if (ssh->cscomp->text_name) + logeventf(ssh, "Initialised %s compression", + ssh->cscomp->text_name); + if (ssh->sccomp->text_name) + logeventf(ssh, "Initialised %s decompression", + ssh->sccomp->text_name); /* * If this is the first key exchange phase, we must pass the @@ -4353,16 +4363,17 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) } while (ret == 0); if (ret < 0) cleanup_exit(0); + c_write_str(ssh, "\r\n"); } - c_write_str(ssh, "\r\n"); s->username[strcspn(s->username, "\n\r")] = '\0'; } else { - char stuff[200]; + char *stuff; strncpy(s->username, cfg.username, sizeof(s->username)); s->username[sizeof(s->username)-1] = '\0'; if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) { - sprintf(stuff, "Using username \"%s\".\r\n", s->username); + stuff = dupprintf("Using username \"%s\".\r\n", s->username); c_write_str(ssh, stuff); + sfree(stuff); } } s->got_username = TRUE; @@ -4390,21 +4401,21 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* Load the pub half of cfg.keyfile so we notice if it's in Pageant */ if (*cfg.keyfile) { int keytype; - logeventf(ssh->frontend, - "Reading private key file \"%.150s\"", cfg.keyfile); + logeventf(ssh, "Reading private key file \"%.150s\"", cfg.keyfile); keytype = key_type(cfg.keyfile); if (keytype == SSH_KEYTYPE_SSH2) { s->publickey_blob = ssh2_userkey_loadpub(cfg.keyfile, NULL, &s->publickey_bloblen); } else { - char msgbuf[256]; - logeventf(ssh->frontend, - "Unable to use this key file (%s)", + char *msgbuf; + logeventf(ssh, "Unable to use this key file (%s)", key_type_to_str(keytype)); - sprintf(msgbuf, "Unable to use key file \"%.150s\" (%s)\r\n", - cfg.keyfile, key_type_to_str(keytype)); + msgbuf = dupprintf("Unable to use key file \"%.150s\"" + " (%s)\r\n", cfg.keyfile, + key_type_to_str(keytype)); c_write_str(ssh, msgbuf); + sfree(msgbuf); s->publickey_blob = NULL; } } else @@ -5117,71 +5128,81 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) char type; int n; int sport,dport,sserv,dserv; - char sports[256], dports[256], host[256]; - char buf[1024]; - struct servent *se; + char sports[256], dports[256], saddr[256], host[256]; ssh->rportfwds = newtree234(ssh_rportcmp_ssh2); /* Add port forwardings. */ ssh->portfwd_strptr = cfg.portfwd; while (*ssh->portfwd_strptr) { type = *ssh->portfwd_strptr++; + saddr[0] = '\0'; n = 0; - while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != '\t') - sports[n++] = *ssh->portfwd_strptr++; + while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != '\t') { + if (*ssh->portfwd_strptr == ':') { + /* + * We've seen a colon in the middle of the + * source port number. This means that + * everything we've seen until now is the + * source _address_, so we'll move it into + * saddr and start sports from the beginning + * again. + */ + ssh->portfwd_strptr++; + sports[n] = '\0'; + strcpy(saddr, sports); + n = 0; + } + if (n < 255) sports[n++] = *ssh->portfwd_strptr++; + } sports[n] = 0; if (*ssh->portfwd_strptr == '\t') ssh->portfwd_strptr++; n = 0; - while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') - host[n++] = *ssh->portfwd_strptr++; + while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') { + if (n < 255) host[n++] = *ssh->portfwd_strptr++; + } host[n] = 0; if (*ssh->portfwd_strptr == ':') ssh->portfwd_strptr++; n = 0; - while (*ssh->portfwd_strptr) - dports[n++] = *ssh->portfwd_strptr++; + while (*ssh->portfwd_strptr) { + if (n < 255) dports[n++] = *ssh->portfwd_strptr++; + } dports[n] = 0; ssh->portfwd_strptr++; dport = atoi(dports); dserv = 0; if (dport == 0) { dserv = 1; - se = getservbyname(dports, NULL); - if (se != NULL) { - dport = ntohs(se->s_port); - } else { - sprintf(buf, - "Service lookup failed for destination port \"%s\"", - dports); - logevent(buf); + dport = net_service_lookup(dports); + if (!dport) { + logeventf(ssh, "Service lookup failed for destination" + " port \"%s\"", dports); } } sport = atoi(sports); sserv = 0; if (sport == 0) { sserv = 1; - se = getservbyname(sports, NULL); - if (se != NULL) { - sport = ntohs(se->s_port); - } else { - sprintf(buf, - "Service lookup failed for source port \"%s\"", - sports); - logevent(buf); + sport = net_service_lookup(sports); + if (!sport) { + logeventf(ssh, "Service lookup failed for source" + " port \"%s\"", sports); } } if (sport && dport) { if (type == 'L') { - pfd_addforward(host, dport, sport, ssh); - sprintf(buf, "Local port %.*s%.*s%d%.*s forwarding to" - " %s:%.*s%.*s%d%.*s", - sserv ? strlen(sports) : 0, sports, - sserv, "(", sport, sserv, ")", - host, - dserv ? strlen(dports) : 0, dports, - dserv, "(", dport, dserv, ")"); - logevent(buf); + pfd_addforward(host, dport, *saddr ? saddr : NULL, + sport, ssh); + 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, ")"); } else { struct ssh_rportfwd *pf; pf = smalloc(sizeof(*pf)); @@ -5189,23 +5210,26 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) pf->dport = dport; pf->sport = sport; if (add234(ssh->rportfwds, pf) != pf) { - sprintf(buf, - "Duplicate remote port forwarding to %s:%d", - host, dport); - logevent(buf); + logeventf(ssh, "Duplicate remote port forwarding" + " to %s:%d", host, dport); sfree(pf); } else { - sprintf(buf, "Requesting remote port %.*s%.*s%d%.*s" - " forward to %s:%.*s%.*s%d%.*s", - sserv ? strlen(sports) : 0, sports, - sserv, "(", sport, sserv, ")", - host, - dserv ? strlen(dports) : 0, dports, - dserv, "(", dport, dserv, ")"); - logevent(buf); + logeventf(ssh, "Requesting remote port " + "%.*s%.*s%.*s%.*s%d%.*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, ")", + host, + (int)(dserv ? strlen(dports) : 0), dports, + dserv, "(", dport, dserv, ")"); ssh2_pkt_init(ssh, SSH2_MSG_GLOBAL_REQUEST); ssh2_pkt_addstring(ssh, "tcpip-forward"); ssh2_pkt_addbool(ssh, 1);/* want reply */ + if (*saddr) + ssh2_pkt_addstring(ssh, saddr); if (cfg.rport_acceptall) ssh2_pkt_addstring(ssh, "0.0.0.0"); else @@ -5739,13 +5763,10 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) } else { char *e = pfd_newconnect(&c->u.pfd.s, realpf->dhost, realpf->dport, c); - char buf[1024]; - sprintf(buf, "Received remote port open request for %s:%d", - realpf->dhost, realpf->dport); - logevent(buf); + logeventf(ssh, "Received remote port open request" + " for %s:%d", realpf->dhost, realpf->dport); if (e != NULL) { - sprintf(buf, "Port open failed: %s", e); - logevent(buf); + logeventf(ssh, "Port open failed: %s", e); error = "Port open failed"; } else { logevent("Forwarded port opened successfully"); @@ -5903,6 +5924,8 @@ static char *ssh_init(void *frontend_handle, void **backend_handle, ssh->do_ssh2_transport_state = NULL; ssh->do_ssh2_authconn_state = NULL; ssh->mainchan = NULL; + ssh->throttled_all = 0; + ssh->v1_stdout_throttling = 0; *backend_handle = ssh; @@ -6101,10 +6124,8 @@ void ssh_send_port_open(void *channel, char *hostname, int port, char *org) { struct ssh_channel *c = (struct ssh_channel *)channel; Ssh ssh = c->ssh; - char buf[1024]; - sprintf(buf, "Opening forwarded connection to %.512s:%d", hostname, port); - logevent(buf); + logeventf(ssh, "Opening forwarded connection to %s:%d", hostname, port); if (ssh->version == 1) { send_packet(ssh, SSH1_MSG_PORT_OPEN,