From 881da16842e210236b12a040a19bf480de3a5a92 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 1 Jun 2008 11:16:32 +0000 Subject: [PATCH] Been meaning to do this for years: introduce a configuration option 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 --- cmdline.c | 7 +++++++ config.c | 8 ++++++++ doc/config.but | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/index.but | 4 ++++ doc/using.but | 16 ++++++++++++++++ putty.h | 1 + raw.c | 16 ++++++++++++++++ rlogin.c | 16 ++++++++++++++++ settings.c | 2 ++ ssh.c | 36 +++++++++++++++++++++++++++++++----- telnet.c | 19 +++++++++++++++++++ windows/winhelp.h | 1 + 12 files changed, 175 insertions(+), 5 deletions(-) diff --git a/cmdline.c b/cmdline.c index 183797df..e0d43929 100644 --- 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; diff --git a/config.c b/config.c index bd07d951..4f01c160 100644 --- 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))); } /* diff --git a/doc/config.but b/doc/config.but index 16d15899..dbf5e2b7 100644 --- a/doc/config.but +++ b/doc/config.but @@ -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 diff --git a/doc/index.but b/doc/index.but index 5a6d6e3a..2b4cef75 100644 --- a/doc/index.but +++ b/doc/index.but @@ -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 diff --git a/doc/using.but b/doc/using.but index 0c7fcf88..85e23431 100644 --- a/doc/using.but +++ b/doc/using.but @@ -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 8f6461e6..25758b25 100644 --- 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 b4b1108f..b2676a93 100644 --- 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; } diff --git a/rlogin.c b/rlogin.c index e40f1597..c9e7c5ec 100644 --- 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; } diff --git a/settings.c b/settings.c index ab2dc925..a175e4d7 100644 --- a/settings.c +++ b/settings.c @@ -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 f22a2b61..5902cbb1 100644 --- 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; } diff --git a/telnet.c b/telnet.c index eeaa76f3..ed685f10 100644 --- 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; } diff --git a/windows/winhelp.h b/windows/winhelp.h index 2dedfc8c..a91aaf12 100644 --- a/windows/winhelp.h +++ b/windows/winhelp.h @@ -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" -- 2.11.0