Support for doing DNS at the proxy end. I've invented a new type of
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index 6c60bd2..62f2a8e 100644 (file)
--- 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);
@@ -1788,7 +1788,7 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
 
     if (cfg.sshbug_derivekey2 == BUG_ON ||
        (cfg.sshbug_derivekey2 == BUG_AUTO &&
-        (wc_match("2.0.*", imp)))) {
+        (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
@@ -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