Been meaning to do this for years: introduce a configuration option
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 1 Jun 2008 11:16:32 +0000 (11:16 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 1 Jun 2008 11:16:32 +0000 (11:16 +0000)
to manually tweak the host name and port number under which the SSH
host key is read and written.

I've put it in the cross-platform Connection panel. Partly under the
flimsy pretext that other backends _can_ use it if they so wish (and
in fact it overrides the host name for title-bar purposes in all
network backends, though it has no other effect in anything but
SSH); but mostly because the SSH panel was too full already :-)

git-svn-id: svn://svn.tartarus.org/sgt/putty@8033 cda61777-01e9-0310-a592-d414129be87e

12 files changed:
cmdline.c
config.c
doc/config.but
doc/index.but
doc/using.but
putty.h
raw.c
rlogin.c
settings.c
ssh.c
telnet.c
windows/winhelp.h

index 183797d..e0d4392 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -203,6 +203,13 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
        strncpy(cfg->username, value, sizeof(cfg->username));
        cfg->username[sizeof(cfg->username) - 1] = '\0';
     }
+    if (!strcmp(p, "-loghost")) {
+       RETURN(2);
+       UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
+       SAVEABLE(0);
+       strncpy(cfg->loghost, value, sizeof(cfg->loghost));
+       cfg->loghost[sizeof(cfg->loghost) - 1] = '\0';
+    }
     if ((!strcmp(p, "-L") || !strcmp(p, "-R") || !strcmp(p, "-D"))) {
        char *fwd, *ptr, *q, *qq;
        int dynamic, i=0;
index bd07d95..4f01c16 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1721,6 +1721,14 @@ void setup_config_box(struct controlbox *b, int midsession,
                          "IPv6", '6', I(ADDRTYPE_IPV6),
                          NULL);
 #endif
+
+           s = ctrl_getset(b, "Connection", "identity",
+                           "Logical name of remote host");
+           ctrl_editbox(s, "Logical name of remote host (e.g. for SSH key lookup):",
+                        'm', 100,
+                        HELPCTX(connection_loghost),
+                        dlg_stdeditbox_handler, I(offsetof(Config,loghost)),
+                        I(sizeof(((Config *)0)->loghost)));
        }
 
        /*
index 16d1589..dbf5e2b 100644 (file)
@@ -1716,6 +1716,54 @@ IPv6 address available, and fall back to IPv4 if not.)
 If you need to force PuTTY to use a particular protocol, you can
 explicitly set this to \q{IPv4} or \q{IPv6}.
 
+\S{config-loghost} \I{logical host name}\q{Logical name of remote host}
+
+\cfg{winhelp-topic}{connection.loghost}
+
+This allows you to tell PuTTY that the host it will really end up
+connecting to is different from where it thinks it is making a
+network connection.
+
+You might use this, for instance, if you had set up an SSH port
+forwarding in one PuTTY session so that connections to some
+arbitrary port (say, \cw{localhost} port 10022) were forwarded to a
+second machine's SSH port (say, \cw{foovax} port 22), and then
+started a second PuTTY connecting to the forwarded port.
+
+In normal usage, the second PuTTY will access the host key cache
+under the host name and port it actually connected to (i.e.
+\cw{localhost} port 10022 in this example). Using the logical host
+name option, however, you can configure the second PuTTY to cache
+the host key under the name of the host \e{you} know that it's
+\e{really} going to end up talking to (here \c{foovax}).
+
+This can be useful if you expect to connect to the same actual
+server through many different channels (perhaps because your port
+forwarding arrangements keep changing): by consistently setting the
+logical host name, you can arrange that PuTTY will not keep asking
+you to reconfirm its host key. Conversely, if you expect to use the
+same local port number for port forwardings to lots of different
+servers, you probably didn't want any particular server's host key
+cached under that local port number.
+
+If you just enter a host name for this option, PuTTY will cache the
+SSH host key under the default SSH port for that host, irrespective
+of the port you really connected to (since the typical scenario is
+like the above example: you connect to a silly real port number and
+your connection ends up forwarded to the normal port-22 SSH server
+of some other machine). To override this, you can append a port
+number to the logical host name, separated by a colon. E.g. entering
+\cq{foovax:2200} as the logical host name will cause the host key to
+be cached as if you had connected to port 2200 of \c{foovax}.
+
+If you provide a host name using this option, it is also displayed
+in other locations which contain the remote host name, such as the
+default window title and the default SSH password prompt. This
+reflects the fact that this is the host you're \e{really} connecting
+to, which is more important than the mere means you happen to be
+using to contact that host. (This applies even if you're using a
+protocol other than SSH.)
+
 \H{config-data} The Data panel
 
 The Data panel allows you to configure various pieces of data which
@@ -2757,6 +2805,12 @@ that forwarding remain open. Similarly, changes to global settings
 such as \q{Local ports accept connections from other hosts} only take
 effect on new forwardings.
 
+If the connection you are forwarding over SSH is itself a second SSH
+connection made by another copy of PuTTY, you might find the
+\q{logical host name} configuration option useful to warn PuTTY of
+which host key it should be expecting. See \k{config-loghost} for
+details of this.
+
 \S{config-ssh-portfwd-localhost} Controlling the visibility of
 forwarded ports
 
index 5a6d6e3..2b4cef7 100644 (file)
@@ -837,3 +837,7 @@ saved sessions from
 
 \IM{PGP signatures} PGP signatures, of PuTTY binaries
 \IM{PGP signatures} signatures, of PuTTY binaries
+
+\IM{logical host name} logical host name
+\IM{logical host name} host name, logical
+\IM{logical host name} host key, caching policy
index 0c7fcf8..85e2343 100644 (file)
@@ -470,6 +470,12 @@ to obtain a fix from Microsoft in order to use addresses like
 For more options relating to port forwarding, see
 \k{config-ssh-portfwd}.
 
+If the connection you are forwarding over SSH is itself a second SSH
+connection made by another copy of PuTTY, you might find the
+\q{logical host name} configuration option useful to warn PuTTY of
+which host key it should be expecting. See \k{config-loghost} for
+details of this.
+
 \H{using-rawprot} Making \i{raw TCP connections}
 
 A lot of \I{debugging Internet protocols}Internet protocols are
@@ -890,6 +896,16 @@ This option is equivalent to the \q{Private key file for
 authentication} box in the Auth panel of the PuTTY configuration box
 (see \k{config-ssh-privkey}).
 
+\S2{using-cmdline-loghost} \i\c{-loghost}: specify a \i{logical host
+name}
+
+This option overrides PuTTY's normal SSH host key caching policy by
+telling it the name of the host you expect your connection to end up
+at (in cases where this differs from the location PuTTY thinks it's
+connecting to). It can be a plain host name, or a host name followed
+by a colon and a port number. See \k{config-loghost} for more detail
+on this.
+
 \S2{using-cmdline-pgpfp} \i\c{-pgpfp}: display \i{PGP key fingerprint}s
 
 This option causes the PuTTY tools not to run as normal, but instead
diff --git a/putty.h b/putty.h
index 8f6461e..25758b2 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -427,6 +427,7 @@ struct config_tag {
     int ping_interval;                /* in seconds */
     int tcp_nodelay;
     int tcp_keepalives;
+    char loghost[512];  /* logical host being contacted, for host key check */
     /* Proxy options */
     char proxy_exclude_list[512];
     int proxy_dns;
diff --git a/raw.c b/raw.c
index b4b1108..b2676a9 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -139,6 +139,22 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
     if ((err = sk_socket_error(raw->s)) != NULL)
        return err;
 
+    if (*cfg->loghost) {
+       char *colon;
+
+       sfree(*realhost);
+       *realhost = dupstr(cfg->loghost);
+       colon = strrchr(*realhost, ':');
+       if (colon) {
+           /*
+            * FIXME: if we ever update this aspect of ssh.c for
+            * IPv6 literal management, this should change in line
+            * with it.
+            */
+           *colon++ = '\0';
+       }
+    }
+
     return NULL;
 }
 
index e40f159..c9e7c5e 100644 (file)
--- a/rlogin.c
+++ b/rlogin.c
@@ -197,6 +197,22 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
        rlogin->bufsize = sk_write(rlogin->s, &z, 1);
     }
 
+    if (*cfg->loghost) {
+       char *colon;
+
+       sfree(*realhost);
+       *realhost = dupstr(cfg->loghost);
+       colon = strrchr(*realhost, ':');
+       if (colon) {
+           /*
+            * FIXME: if we ever update this aspect of ssh.c for
+            * IPv6 literal management, this should change in line
+            * with it.
+            */
+           *colon++ = '\0';
+       }
+    }
+
     return NULL;
 }
 
index ab2dc92..a175e4d 100644 (file)
@@ -332,6 +332,7 @@ void save_open_settings(void *sesskey, Config *cfg)
     write_setting_i(sesskey, "AuthKI", cfg->try_ki_auth);
     write_setting_i(sesskey, "SshNoShell", cfg->ssh_no_shell);
     write_setting_i(sesskey, "SshProt", cfg->sshprot);
+    write_setting_s(sesskey, "LogHost", cfg->loghost);
     write_setting_i(sesskey, "SSH2DES", cfg->ssh2_des_cbc);
     write_setting_filename(sesskey, "PublicKeyFile", cfg->keyfile);
     write_setting_s(sesskey, "RemoteCommand", cfg->remote_cmd);
@@ -608,6 +609,7 @@ void load_open_settings(void *sesskey, Config *cfg)
     gpps(sesskey, "RekeyBytes", "1G", cfg->ssh_rekey_data,
         sizeof(cfg->ssh_rekey_data));
     gppi(sesskey, "SshProt", 2, &cfg->sshprot);
+    gpps(sesskey, "LogHost", "", cfg->loghost, sizeof(cfg->loghost));
     gppi(sesskey, "SSH2DES", 0, &cfg->ssh2_des_cbc);
     gppi(sesskey, "SshNoAuth", 0, &cfg->ssh_no_userauth);
     gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth);
diff --git a/ssh.c b/ssh.c
index f22a2b6..5902cbb 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -2837,12 +2837,30 @@ static const char *connect_to_host(Ssh ssh, char *host, int port,
     SockAddr addr;
     const char *err;
 
-    ssh->savedhost = snewn(1 + strlen(host), char);
-    strcpy(ssh->savedhost, host);
+    if (*ssh->cfg.loghost) {
+       char *colon;
 
-    if (port < 0)
-       port = 22;                     /* default ssh port */
-    ssh->savedport = port;
+       ssh->savedhost = dupstr(ssh->cfg.loghost);
+       ssh->savedport = 22;           /* default ssh port */
+
+       /*
+        * A colon suffix on savedhost also lets us affect
+        * savedport.
+        * 
+        * (FIXME: do something about IPv6 address literals here.)
+        */
+       colon = strrchr(ssh->savedhost, ':');
+       if (colon) {
+           *colon++ = '\0';
+           if (*colon)
+               ssh->savedport = atoi(colon);
+       }
+    } else {
+       ssh->savedhost = dupstr(host);
+       if (port < 0)
+           port = 22;                 /* default ssh port */
+       ssh->savedport = port;
+    }
 
     /*
      * Try to find host.
@@ -2880,6 +2898,14 @@ static const char *connect_to_host(Ssh ssh, char *host, int port,
        ssh_send_verstring(ssh, NULL);
     }
 
+    /*
+     * loghost, if configured, overrides realhost.
+     */
+    if (*ssh->cfg.loghost) {
+       sfree(*realhost);
+       *realhost = dupstr(ssh->cfg.loghost);
+    }
+
     return NULL;
 }
 
index eeaa76f..ed685f1 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -805,6 +805,25 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
      */
     update_specials_menu(telnet->frontend);
 
+    /*
+     * loghost overrides realhost, if specified.
+     */
+    if (*telnet->cfg.loghost) {
+       char *colon;
+
+       sfree(*realhost);
+       *realhost = dupstr(telnet->cfg.loghost);
+       colon = strrchr(*realhost, ':');
+       if (colon) {
+           /*
+            * FIXME: if we ever update this aspect of ssh.c for
+            * IPv6 literal management, this should change in line
+            * with it.
+            */
+           *colon++ = '\0';
+       }
+    }
+
     return NULL;
 }
 
index 2dedfc8..a91aaf1 100644 (file)
@@ -74,6 +74,7 @@
 #define WINHELP_CTX_connection_nodelay "connection.nodelay:config-nodelay"
 #define WINHELP_CTX_connection_ipversion "connection.ipversion:config-address-family"
 #define WINHELP_CTX_connection_tcpkeepalive "connection.tcpkeepalive:config-tcp-keepalives"
+#define WINHELP_CTX_connection_loghost "connection.loghost:config-loghost"
 #define WINHELP_CTX_proxy_type "proxy.type:config-proxy-type"
 #define WINHELP_CTX_proxy_main "proxy.main:config-proxy"
 #define WINHELP_CTX_proxy_exclude "proxy.exclude:config-proxy-exclude"