From 44f578e47975f53d824429ccad48b3394629a8ba Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Sat, 31 May 2008 17:11:16 +0000 Subject: [PATCH 1/3] Update for `win-randseed-location' fix. [originally from svn r8029] --- doc/faq.but | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/faq.but b/doc/faq.but index 9c85deb8..abd5ebd2 100644 --- a/doc/faq.but +++ b/doc/faq.but @@ -383,10 +383,9 @@ while host keys are stored under \c{SshHostKeys}. PuTTY also requires a random number seed file, to improve the unpredictability of randomly chosen data needed as part of the SSH -cryptography. This is stored by default in a file called \i\c{PUTTY.RND} -in your Windows home directory (\c{%HOMEDRIVE%\\%HOMEPATH%}), or in -the actual Windows directory (such as \c{C:\\WINDOWS}) if the home -directory doesn't exist, for example if you're using Win95. If you +cryptography. This is stored by default in a file called \i\c{PUTTY.RND}; +this is stored by default in the \q{Application Data} directory, +or failing that, one of a number of fallback locations. If you want to change the location of the random number seed file, you can put your chosen pathname in the Registry, at From 33bfb2bc722222dddbc5024a3cb2a7d69ec1cb6d Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Sat, 31 May 2008 17:22:29 +0000 Subject: [PATCH 2/3] Apparently Vista's printf-like functions don't support %n by default. We could explicitly re-enable %n, but we only use it in one place, so take the path of least resistance and remove that single instance. This stops dupvprintf() getting stuck in a loop (a behaviour that's caused by a workaround for a broken libc). [originally from svn r8030] --- ssh.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ssh.c b/ssh.c index eec05808..f22a2b61 100644 --- a/ssh.c +++ b/ssh.c @@ -8569,7 +8569,7 @@ static void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin) { /* log reason code in disconnect message */ char *buf, *msg; - int nowlen, reason, msglen; + int reason, msglen; reason = ssh_pkt_getuint32(pktin); ssh_pkt_getstring(pktin, &msg, &msglen); @@ -8583,14 +8583,14 @@ static void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin) } logevent(buf); sfree(buf); - buf = dupprintf("Disconnection message text: %n%.*s", - &nowlen, msglen, msg); + buf = dupprintf("Disconnection message text: %.*s", + msglen, msg); logevent(buf); - bombout(("Server sent disconnect message\ntype %d (%s):\n\"%s\"", + bombout(("Server sent disconnect message\ntype %d (%s):\n\"%.*s\"", reason, (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ? ssh2_disconnect_reasons[reason] : "unknown", - buf+nowlen)); + msglen, msg)); sfree(buf); } From e81a8cf795825bc133678d33c4e2ca4585edf811 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 1 Jun 2008 11:16:32 +0000 Subject: [PATCH 3/3] 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 :-) [originally from svn r8033] --- 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"