X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/57356d6317f6f33dd622711d305c4579df63b269..b7a189f38294c745ae4ea6efb55891c8196e275b:/ssh.c diff --git a/ssh.c b/ssh.c index 2df71102..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); @@ -1073,7 +1073,7 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen) logevent(buf); sfree(buf); buf = dupprintf("Disconnection message text: %n%.*s", - msglen, &nowlen, ssh->pktin.data + 14); + &nowlen, msglen, ssh->pktin.data + 14); logevent(buf); bombout((ssh,"Server sent disconnect message\ntype %d (%s):\n\"%s\"", reason, @@ -1776,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. */ @@ -1788,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 @@ -1800,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. */ @@ -1811,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"); @@ -2072,7 +2072,7 @@ static char *connect_to_host(Ssh ssh, char *host, int port, * Try to find host. */ logeventf(ssh, "Looking up host \"%s\"", host); - addr = sk_namelookup(host, realhost); + addr = name_lookup(host, port, realhost); if ((err = sk_addr_error(addr))) return err; @@ -3071,28 +3071,46 @@ 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 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); @@ -3117,9 +3135,12 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) } if (sport && dport) { if (type == 'L') { - pfd_addforward(host, dport, sport, ssh); - logeventf(ssh, "Local port %.*s%.*s%d%.*s forwarding to" - " %s:%.*s%.*s%d%.*s", + 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, @@ -3130,6 +3151,11 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) 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) { logeventf(ssh, "Duplicate remote port forwarding to %s:%d", @@ -4375,8 +4401,7 @@ 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 = @@ -4384,8 +4409,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) &s->publickey_bloblen); } else { char *msgbuf; - logeventf(ssh->frontend, - "Unable to use this key file (%s)", + logeventf(ssh, "Unable to use this key file (%s)", key_type_to_str(keytype)); msgbuf = dupprintf("Unable to use key file \"%.150s\"" " (%s)\r\n", cfg.keyfile, @@ -5104,28 +5128,46 @@ 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 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); @@ -5150,9 +5192,12 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) } if (sport && dport) { if (type == 'L') { - pfd_addforward(host, dport, sport, ssh); - logeventf(ssh, "Local port %.*s%.*s%d%.*s forwarding to" - " %s:%.*s%.*s%d%.*s", + 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, @@ -5169,8 +5214,12 @@ 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%d%.*s" + 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, @@ -5179,6 +5228,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) 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