All but one caller was doing this unconditionally. The one conditional
call was when initialising the main channel, and in consequence PuTTY
leaked a channel structure when the server refused to open the main
channel. Now it doesn't.
An opcode for this was recently published in
https://tools.ietf.org/html/draft-sgtatham-secsh-iutf8-00 .
The default setting is conditional on frontend_is_utf8(), which is
consistent with the pty back end's policy for setting the same flag
locally. Of course, users can override the setting either way in the
GUI configurer, the same as all other tty modes.
Previously, the code that marshalled tty settings into the "pty-req"
request was iterating through the subkeys stored in ssh->conf, meaning
that if a session had been saved before we gained support for a
particular tty mode, the iteration wouldn't visit that mode at all and
hence wouldn't send even the default setting for it.
Now we iterate over the array of known mode identifiers in
ssh_ttymodes[] and look each one up in ssh->conf, rather than vice
versa. This means that when we add support for a new tty mode with a
nontrivial policy for choosing its default state, we should start
using the default handler immediately, rather than bizarrely waiting
for users to save a session after the change.
Also add an assertion to do_ssh2_transport to catch this.
This bug would be highly unlikely to manifest accidentally, but I
think you could trigger it by setting the data-based rekey threshold
very low.
All calls to ssh2_add_channel_data() were followed by a call to
ssh2_try_send(), so it seems sensible to replace ssh2_add_channel_data()
with ssh2_send_channel_data(), which does both.
Specifically, don't try to unblock all channels just because we've got
something to send on the main one. It looks like the code to do that
was left over from when SSH_MSG_CHANNEL_ADJUST was handled in
do_ssh2_authconn().
The UI now only has "1" and "2" options for SSH protocol version, which
behave like the old "1 only" and "2 only" options; old
SSH-N-with-fallback settings are interpreted as SSH-N-only.
This prevents any attempt at a protocol downgrade attack.
Most users should see no difference; those poor souls who still have to
work with SSH-1 equipment now have to explicitly opt in.
If you're connecting to a new server and it _only_ provides host key
types you've configured to be below the warning threshold, it's OK to
give the standard askalg() message. But if you've newly demoted a host
key type and now reconnect to some server for which that type was the
best key you had cached, the askalg() wording isn't really appropriate
(it's not that the key we've settled on is the first type _supported
by the server_, it's that it's the first type _cached by us_), and
also it's potentially helpful to list the better algorithms so that
the user can pick one to cross-certify.
When Jacob introduced this message in d0d3c47a0, he was right to
assume that hostkey_algs[] and ssh->uncert_hostkeys[] were sorted in
the same order. Unfortunately, he became wrong less than an hour later
when I committed d06098622. Now we avoid making any such assumption.
Since we got a dynamic preference order, it's been bailing out at a
random point, and listing keys we wouldn't use.
(It would still be nice to only mention keys that we'd actually use, but
that's now quite fiddly.)
I noticed this in passing while tinkering with the hostkey_algs array:
these arrays are full of pointers-to-const, but are not also
themselves declared const, which they should have been all along.
Now we actually have enough of them to worry about, and especially
since some of the types we support are approved by organisations that
people might make their own decisions about whether to trust, it seems
worth having a config list for host keys the same way we have one for
kex types and ciphers.
To make room for this, I've created an SSH > Host Keys config panel,
and moved the existing host-key related configuration (manually
specified fingerprints) into there from the Kex panel.
I got momentarily confused between whether the special code
(TS_LOCALSTART+i) meant the ith entry in the variable
uncert_hostkeys[] array, or the ith entry in the fixed hostkey_algs[]
array. Now I think everything agrees on it being the latter.
If a server offers host key algorithms that we don't have a stored key
for, they will now appear in a submenu of the Special Commands menu.
Selecting one will force a repeat key exchange with that key, and if
it succeeds, will add the new host key to the cache. The idea is that
the new key sent by the server is protected by the crypto established
in the previous key exchange, so this is just as safe as typing some
command like 'ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub' at the
server prompt and transcribing the results manually.
This allows switching over to newer host key algorithms if the client
has begun to support them (e.g. people using PuTTY's new ECC
functionality for the first time), or if the server has acquired a new
key (e.g. due to a server OS upgrade).
At the moment, it's only available manually, for a single host key
type at a time. Automating it is potentially controversial for
security policy reasons (what if someone doesn't agree this is what
they want in their host key cache, or doesn't want to switch over to
using whichever of the keys PuTTY would now put top of the list?), for
code plumbing reasons (chaining several of these rekeys might be more
annoying than doing one at a time) and for CPU usage reasons (rekeys
are expensive), but even so, it might turn out to be a good idea in
future.
The last list we returned is now stored in the main Ssh structure
rather than being a static array in ssh_get_specials.
The main point of this is that I want to start adding more dynamic
things to it, for which I can't predict the array's max length in
advance.
But also this fixes a conceptual wrongness, in that if a process had
more than one Ssh instance in it then their specials arrays would have
taken turns occupying the old static array, and although the current
single-threaded client code in the GUI front ends wouldn't have minded
(it would have read out the contents just once immediately after
get_specials returned), it still feels as if it was a bug waiting to
happen.
ssh_pkt_getstring can return (NULL,0) if the input packet is too short
to contain a valid string.
In quite a few places we were passing the returned pointer,length pair
to a printf function with "%.*s" type format, which seems in practice
to have not been dereferencing the pointer but the C standard doesn't
actually guarantee that. In one place we were doing the same job by
hand with memcpy, and apparently that _can_ dereference the pointer in
practice (so a server could have caused a NULL-dereference crash by
sending an appropriately malformed "x11" type channel open request).
And also I spotted a logging call in the "forwarded-tcpip" channel
open handler which had forgotten the field width completely, so it was
erroneously relying on the string happening to be NUL-terminated in
the received packet.
I've tightened all of this up in general by normalising (NULL,0) to
("",0) before calling printf("%.*s"), and replacing the two even more
broken cases with the corrected version of that same idiom.
It has three settings: on, off, and 'only until session starts'. The
idea of the last one is that if you use something like 'ssh -v' as
your proxy command, you probably wanted to see the initial SSH
connection-setup messages while you were waiting to see if the
connection would be set up successfully at all, but probably _didn't_
want a slew of diagnostics from rekeys disrupting your terminal in
mid-emacs once the session had got properly under way.
Default is off, to avoid startling people used to the old behaviour. I
wonder if I should have set it more aggressively, though.
I'm about to want to make a change to all those functions at once, and
since they're almost identical, it seemed easiest to pull them out
into a common helper. The new source file be_misc.c is intended to
contain helper code common to all network back ends (crypto and
non-crypto, in particular), and initially it contains a
backend_socket_log() function which is the common part of ssh_log(),
telnet_log(), rlogin_log() etc.
We've always had the back-end code unconditionally print 'Looking up
host' before calling name_lookup. But name_lookup doesn't always do an
actual lookup - in cases where the connection will be proxied and
we're configured to let the proxy do the DNS for us, it just calls
sk_nonamelookup to return a dummy SockAddr with the unresolved name
still in it. It's better to print a message that varies depending on
whether we're _really_ doing DNS or not, e.g. so that people can tell
the difference between DNS failure and proxy misconfiguration.
Hence, those log messages are now generated inside name_lookup(),
which takes a couple of extra parameters for the purpose - a frontend
pointer to pass to logevent(), and a reason string so that it can say
what the hostname it's (optionally) looking up is going to be used
for. (The latter is intended for possible use in logging subsidiary
lookups for port forwarding, though the moment I haven't changed
the current setup where those connection setups aren't logged in
detail - we just pass NULL in that situation.)
When we set ssh->sc{cipher,mac} to s->sc{cipher,mac}_tobe
conditionally, we should be conditionalising on the values we're
_reading_, not the ones we're about to overwrite.
Thanks to Colin Harrison for this patch.
Apparently if you maintain a branch for a long time where you only
compile with a non-default ifdef enabled, it becomes possible to not
notice a typo you left in the default branch :-)
This adds the "none" cipher and MAC, and also disables kex signure
verification and host-key checking. Since a client like this is
completely insecure, it also rewrites the client version string to
start "ISH", which should make it fail to interoperate with a real SSH
server. The server version string is still expected to begin "SSH" so
the real packet captures can be used against it.
The previous assertion failure is obviously wrong, but RFC 4253 doesn't
explicitly declare them to be a protocol error. Currently, the incoming
packet isn't logged, which might cause some confusion for log parsers.
Bug found with the help of afl-fuzz.
The previous assertion failure is obviously wrong, but RFC 4253 doesn't
explicitly declare them to be a protocol error. Currently, the incoming
packet isn't logged, which might cause some confusion for log parsers.
Bug found with the help of afl-fuzz.
This protects the Unix platform sharing code in the case where no salt
file exists yet in the connection-sharing directory, in which case
make_dirname() will want to create one by using some random bytes, and
prior to this commit, would fail an assertion because the random
number generator wasn't set up.
It would be neater to just return FALSE from ssh_test_for_upstream in
that situation - if there's no salt file, then no sharing socket can
be valid anyway - but that would involve doing more violence to the
code structure than I'm currently prepared to do for a minor elegance
gain.
A user reports that in a particular situation one of the calls to
LoadLibrary from wingss.c has unwanted side effects, and points out
that this happens even when the saved session has GSSAPI disabled. So
I've evaluated as much as possible of the condition under which we
check the results of GSS library loading, and deferred the library
loading itself until after that condition says we even care about the
results.
(cherry picked from commit 9a08d9a7c1)
A Plink invocation of the form 'plink -shareexists <session>' tests
for a currently live connection-sharing upstream for the session in
question. <session> can be any syntax you'd use with Plink to make the
actual connection (a host/port number, a bare saved session name,
-load, whatever).
I envisage this being useful for things like adaptive proxying - e.g.
if you want to connect to host A which you can't route to directly,
and you might already have a connection to either of hosts B or C
which are viable proxies, then you could write a proxy shell script
which checks whether you already have an upstream for B or C and goes
via whichever one is currently active.
Testing for the upstream's existence has to be done by actually
connecting to its socket, because on Unix the mere existence of a
Unix-domain socket file doesn't guarantee that there's a process
listening to it. So we make a test connection, and then immediately
disconnect; hence, that shows up in the upstream's event log.
This is the part of ssh.c's connect_to_host() which figures out the
host name and port number that logically identify the connection -
i.e. not necessarily where we physically connected to, but what we'll
use to look up the saved session cache, put in the window title bar,
and give to the connection sharing code to identify other connections
to share with.
I'm about to want to use it for another purpose, so it needs to be
moved out into a separate function.
If we've chosen the ChaCha20-Poly1305 option for a cipher, then that
forces the use of its associated MAC. In that situation, we should
avoid even _trying_ to figure out a MAC by examining the MAC string
from the server's KEXINIT, because we won't use the MAC selected by
that method anyway, so there's no point imposing the requirement on
servers to present a MAC we believe in just so we know it's there.
This was breaking interoperation with tinysshd, and is in violation of
OpenSSH's spec for the "chacha20-poly1305@openssh.com" cipher.
The revamp of key generation in commit e460f3083 made the assumption
that you could decide how many bytes of key material to generate by
converting cipher->keylen from bits to bytes. This is a good
assumption for all ciphers except DES/3DES: since the SSH DES key
setup ignores one bit in every byte of key material it's given, you
need more bytes than its keylen field would have you believe. So
currently the DES ciphers aren't being keyed correctly.
The original keylen field is used for deciding how big a DH group to
request, and on that basis I think it still makes sense to keep it
reflecting the true entropy of a cipher key. So it turns out we need
two _separate_ key length fields per cipher - one for the real
entropy, and one for the much more obvious purpose of knowing how much
data to ask for from ssh2_mkkey.
A compensatory advantage, though, is that we can now measure the
latter directly in bytes rather than bits, so we no longer have to
faff about with dividing by 8 and rounding up.
Tim Kosse points out that we now support some combinations of crypto
primitives which break the hardwired assumption that two blocks of
hash output from the session-key derivation algorithm are sufficient
to key every cipher and MAC in the system.
So now ssh2_mkkey is given the desired key length, and performs as
many iterations as necessary.
The key derivation code has been assuming (though non-critically, as
it happens) that the size of the MAC output is the same as the size of
the MAC key. That isn't even a good assumption for the HMAC family,
due to HMAC-SHA1-96 and also the bug-compatible versions of HMAC-SHA1
that only use 16 bytes of key material; so now we have an explicit
key-length field separate from the MAC-length field.
A user reports that in a particular situation one of the calls to
LoadLibrary from wingss.c has unwanted side effects, and points out
that this happens even when the saved session has GSSAPI disabled. So
I've evaluated as much as possible of the condition under which we
check the results of GSS library loading, and deferred the library
loading itself until after that condition says we even care about the
results.
If a sharing downstream disconnected while we were still in userauth
(probably by deliberate user action, since such a downstream would
have just been sitting there waiting for upstream to be ready for it)
then we could crash by attempting to count234(ssh->channels) before
the ssh->channels tree had been set up in the first place.
A simple null-pointer check fixes it. Thanks to Antti Seppanen for the
report.
I removed a vital line of code while fixing the merge conflicts when
cherry-picking 1eb578a488 as
26fe1e26c0, causing Diffie-Hellman key
exchange to be completely broken because the server's host key was
never constructed to verify the signature with. Reinstate it.
Assorted calls to ssh_pkt_getstring in handling the later parts of key
exchange (post-KEXINIT) were not checked for NULL afterwards, so that
a variety of badly formatted key exchange packets would cause a crash
rather than a sensible error message.
None of these is an exploitable vulnerability - the server can only
force a clean null-deref crash, not an access to actually interesting
memory.
Thanks to '3unnym00n' for pointing out one of these, causing me to
find all the rest of them too.
(cherry picked from commit 1eb578a488)
Conflicts:
ssh.c
Cherry-picker's notes: the main conflict arose because the original
commit also made fixes to the ECDH branch of the big key exchange if
statement, which doesn't exist on this branch. Also there was a minor
and purely textual conflict, when an error check was added right next
to a function call that had acquired an extra parameter on master.
The final main loop in do_ssh2_authconn will sometimes loop over all
currently open channels calling ssh2_try_send_and_unthrottle. If the
channel is a sharing one, however, that will reference fields of the
channel structure like 'remwindow', which were never initialised in
the first place (thanks, valgrind). Fix by excluding CHAN_SHARING
channels from that loop.
(cherry picked from commit 7366fde1d4)
When anyone connects to a PuTTY tool's listening socket - whether it's
a user of a local->remote port forwarding, a connection-sharing
downstream or a client of Pageant - we'd like to log as much
information as we can find out about where the connection came from.
To that end, I've implemented a function sk_peer_info() in the socket
abstraction, which returns a freeform text string as best it can (or
NULL, if it can't get anything at all) describing the thing at the
other end of the connection. For TCP connections, this is done using
getpeername() to get an IP address and port in the obvious way; for
Unix-domain sockets, we attempt SO_PEERCRED (conditionalised on some
moderately hairy autoconfery) to get the pid and owner of the peer. I
haven't implemented anything for Windows named pipes, but I will if I
hear of anything useful.
(cherry picked from commit c8f83979a3)
Conflicts:
pageant.c
Cherry-picker's notes: the conflict was because the original commit
also added a use of the same feature in the centralised Pageant code,
which doesn't exist on this branch. Also I had to remove 'const' from
the type of the second parameter to wrap_send_port_open(), since this
branch hasn't had the same extensive const-fixing as master.
PuTTY now uses the updated version of Diffie-Hellman group exchange,
except for a few old OpenSSH versions which Darren Tucker reports only
support the old version.
FIXME: this needs further work because the Bugs config panel has now
overflowed.
(cherry picked from commit 62a1bce7cb)
Assorted calls to ssh_pkt_getstring in handling the later parts of key
exchange (post-KEXINIT) were not checked for NULL afterwards, so that
a variety of badly formatted key exchange packets would cause a crash
rather than a sensible error message.
None of these is an exploitable vulnerability - the server can only
force a clean null-deref crash, not an access to actually interesting
memory.
Thanks to '3unnym00n' for pointing out one of these, causing me to
find all the rest of them too.
The final main loop in do_ssh2_authconn will sometimes loop over all
currently open channels calling ssh2_try_send_and_unthrottle. If the
channel is a sharing one, however, that will reference fields of the
channel structure like 'remwindow', which were never initialised in
the first place (thanks, valgrind). Fix by excluding CHAN_SHARING
channels from that loop.
I'd rather see the cipher and MAC named separately, with a hint that
the two are linked together in some way, than see the cipher called by
a name including the MAC and the MAC init message have an ugly
'<implicit>' in it.
This allows for sharing a bit of code, and it also means that
deduplication of KEXINIT algorithms can be done while working out the
list of algorithms rather than when constructing the KEXINIT packet
itself.
The general plan is that if PuTTY knows a host key for a server, it
should preferentially ask for the same type of key so that there's some
chance of actually getting the same key again. This should mean that
when a server (or PuTTY) adds a new host key type, PuTTY doesn't
gratuitously switch to that key type and then warn the user about an
unrecognised key.
It seems like quite an important thing to mention in the event log!
Suppose there's a bug affecting only one curve, for example? Fixed-
group Diffie-Hellman has always logged the group, but the ECDH log
message just told you the hash and not also the curve.
To implement this, I've added a 'textname' field to all elliptic
curves, whether they're used for kex or signing or both, suitable for
use in this log message and any others we might find a need for in
future.
When anyone connects to a PuTTY tool's listening socket - whether it's
a user of a local->remote port forwarding, a connection-sharing
downstream or a client of Pageant - we'd like to log as much
information as we can find out about where the connection came from.
To that end, I've implemented a function sk_peer_info() in the socket
abstraction, which returns a freeform text string as best it can (or
NULL, if it can't get anything at all) describing the thing at the
other end of the connection. For TCP connections, this is done using
getpeername() to get an IP address and port in the obvious way; for
Unix-domain sockets, we attempt SO_PEERCRED (conditionalised on some
moderately hairy autoconfery) to get the pid and owner of the peer. I
haven't implemented anything for Windows named pipes, but I will if I
hear of anything useful.
The new code remembers the contents and meaning of the outgoing KEXINIT
and uses this to drive the algorithm negotiation, rather than trying to
reconstruct what the outgoing KEXINIT probably said. This removes the
need to maintain the KEXINIT generation and parsing code precisely in
parallel.
It also fixes a bug whereby PuTTY would have selected the wrong host key
type in cases where the server gained a host key type between rekeys.
Having found a lot of unfixed constness issues in recent development,
I thought perhaps it was time to get proactive, so I compiled the
whole codebase with -Wwrite-strings. That turned up a huge load of
const problems, which I've fixed in this commit: the Unix build now
goes cleanly through with -Wwrite-strings, and the Windows build is as
close as I could get it (there are some lingering issues due to
occasional Windows API functions like AcquireCredentialsHandle not
having the right constness).
Notable fallout beyond the purely mechanical changing of types:
- the stuff saved by cmdline_save_param() is now explicitly
dupstr()ed, and freed in cmdline_run_saved.
- I couldn't make both string arguments to cmdline_process_param()
const, because it intentionally writes to one of them in the case
where it's the argument to -pw (in the vain hope of being at least
slightly friendly to 'ps'), so elsewhere I had to temporarily
dupstr() something for the sake of passing it to that function
- I had to invent a silly parallel version of const_cmp() so I could
pass const string literals in to lookup functions.
- stripslashes() in pscp.c and psftp.c has the annoying strchr nature
The ec_name_to_curve and ec_curve_to_name functions shouldn't really
have had to exist at all: whenever any part of the PuTTY codebase
starts using sshecc.c, it's starting from an ssh_signkey or ssh_kex
pointer already found by some other means. So if we make sure not to
lose that pointer, we should never need to do any string-based lookups
to find the curve we want, and conversely, when we need to know the
name of our curve or our algorithm, we should be able to look it up as
a straightforward const char * starting from the algorithm pointer.
This commit cleans things up so that that is indeed what happens. The
ssh_signkey and ssh_kex structures defined in sshecc.c now have
'extra' fields containing pointers to all the necessary stuff;
ec_name_to_curve and ec_curve_to_name have been completely removed;
struct ec_curve has a string field giving the curve's name (but only
for those curves which _have_ a name exposed in the wire protocol,
i.e. the three NIST ones); struct ec_key keeps a pointer to the
ssh_signkey it started from, and uses that to remember the algorithm
name rather than reconstructing it from the curve. And I think I've
got rid of all the ad-hockery scattered around the code that switches
on curve->fieldBits or manually constructs curve names using stuff
like sprintf("nistp%d"); the only remaining switch on fieldBits
(necessary because that's the UI for choosing a curve in PuTTYgen) is
at least centralised into one place in sshecc.c.
One user-visible result is that the format of ed25519 host keys in the
registry has changed: there's now no curve name prefix on them,
because I think it's not really right to make up a name to use. So any
early adopters who've been using snapshot PuTTY in the last week will
be inconvenienced; sorry about that.
This gives families of public key and kex functions (by which I mean
those sharing a set of methods) a place to store parameters that allow
the methods to vary depending on which exact algorithm is in use.
The ssh_kex structure already had a set of parameters specific to
Diffie-Hellman key exchange; I've moved those into sshdh.c and made
them part of the 'extra' structure for that family only, so that
unrelated kex methods don't have to faff about saying NULL,NULL,0,0.
(This required me to write an extra accessor function for ssh.c to ask
whether a DH method was group-exchange style or fixed-group style, but
that doesn't seem too silly.)
Not all of them, but the ones that don't get a 'void *key' parameter.
This means I can share methods between multiple ssh_signkey
structures, and still give those methods an easy way to find out which
public key method they're dealing with, by loading parameters from a
larger structure in which the ssh_signkey is the first element.
(In OO terms, I'm arranging that all static methods of my public key
classes get a pointer to the class vtable, to make up for not having a
pointer to the class instance.)
I haven't actually done anything with the new facility in this commit,
but it will shortly allow me to clean up the constant lookups by curve
name in the ECDSA code.
All the name strings in ssh_cipher, ssh_mac, ssh_hash, ssh_signkey
point to compile-time string literals, hence should obviously be const
char *.
Most of these const-correctness patches are just a mechanical job of
adding a 'const' in the one place you need it right now, and then
chasing the implications through the code adding further consts until
it compiles. But this one has actually shown up a bug: the 'algorithm'
output parameter in ssh2_userkey_loadpub was sometimes returning a
pointer to a string literal, and sometimes a pointer to dynamically
allocated memory, so callers were forced to either sometimes leak
memory or sometimes free a bad thing. Now it's consistently
dynamically allocated, and should be freed everywhere too.
There were ad-hoc functions for fingerprinting a bare key blob in both
cmdgen.c and pageant.c, not quite doing the same thing. Also, every
SSH-2 public key algorithm in the code base included a dedicated
fingerprint() method, which is completely pointless since SSH-2 key
fingerprints are computed in an algorithm-independent way (just hash
the standard-format public key blob), so each of those methods was
just duplicating the work of the public_blob() method with a less
general output mechanism.
Now sshpubk.c centrally provides an ssh2_fingerprint_blob() function
that does all the real work, plus an ssh2_fingerprint() function that
wraps it and deals with calling public_blob() to get something to
fingerprint. And the fingerprint() method has been completely removed
from ssh_signkey and all its implementations, and good riddance.
Obviously PuTTY can't actually do public-key authentication itself, if
you give it a public rather than private key file. But it can still
match the supplied public key file against the list of keys in the
agent, and narrow down to that. So if for some reason you're
forwarding an agent to a machine you don't want to trust with your
_private_ key file (even encrypted), you can still use the '-i' option
to select which key from the agent to use, by uploading just the
public key file to that machine.
It's just ssh_pkt_addstring_data but using strlen to get the length of
string to add, so make that explicit by having it call
ssh_pkt_addstring_data. Good compilers should be unaffected by this
change.
This is the kex protocol id "curve25519-sha256@libssh.org", so called
because it's over the prime field of order 2^255 - 19.
Arithmetic in this curve is done using the Montgomery representation,
rather than the Weierstrass representation. So 'struct ec_curve' has
grown a discriminant field and a union of subtypes.
Several of the functions in ssh2_signkey, and one or two SSH-1 key
functions too, were still taking assorted non-const buffer parameters
that had never been properly constified. Sort them all out.
This causes the initial length field of the SSH-2 binary packet to be
unencrypted (with the knock-on effect that now the packet length not
including MAC must be congruent to 4 rather than 0 mod the cipher
block size), and then the MAC is applied over the unencrypted length
field and encrypted ciphertext (prefixed by the sequence number as
usual). At the cost of exposing some information about the packet
lengths to an attacker (but rarely anything they couldn't have
inferred from the TCP headers anyway), this closes down any
possibility of a MITM using the client as a decryption oracle, unless
they can _first_ fake a correct MAC.
ETM mode is enabled by means of selecting a different MAC identifier,
all the current ones of which are constructed by appending
"-etm@openssh.com" to the name of a MAC that already existed.
We currently prefer the original SSH-2 binary packet protocol (i.e. we
list all the ETM-mode MACs last in our KEXINIT), on the grounds that
it's better tested and more analysed, so at the moment the new mode is
only activated if a server refuses to speak anything else.
PuTTY now uses the updated version of Diffie-Hellman group exchange,
except for a few old OpenSSH versions which Darren Tucker reports only
support the old version.
FIXME: this needs further work because the Bugs config panel has now
overflowed.
Florent Daigniere of Matta points out that RFC 4253 actually
_requires_ us to refuse to accept out-of-range values, though it isn't
completely clear to me why this should be a MUST on the receiving end.
Matta considers this to be a security vulnerability, on the grounds
that if a server should accidentally send an obviously useless value
such as 1 then we will fail to reject it and agree a key that an
eavesdropper could also figure out. Their id for this vulnerability is
MATTA-2015-002.
I'm not actually sure why we've always had back ends notify ldisc of
changes to echo/edit settings by giving ldisc_send(ldisc,NULL,0,0) a
special meaning, instead of by having a separate dedicated notify
function with its own prototype and parameter set. Coverity's recent
observation that the two kinds of call don't even have the same
requirements on the ldisc (particularly, whether ldisc->term can be
NULL) makes me realise that it's really high time I separated the two
conceptually different operations into actually different functions.
While I'm here, I've renamed the confusing ldisc_update() function
which that special operation ends up feeding to, because it's not
actually a function applying to an ldisc - it applies to a front end.
So ldisc_send(ldisc,NULL,0,0) is now ldisc_echoedit_update(ldisc), and
that in turn figures out the current echo/edit settings before passing
them on to frontend_echoedit_update(). I think that should be clearer.
This ought to happen in ssh_do_close alongside the code that shuts
down other local listening things like port forwardings, for the same
obvious reason. In particular, we should get through this _before_ we
put up a modal dialog box telling the user what just went wrong with
the SSH connection, so that further sessions started while that box is
active don't try futilely to connect to the not-really-listening
zombie upstream.
This provides support for ECDSA public keys, for both hosts and users,
and also ECDH key exchange. Supported curves are currently just the
three NIST curves required by RFC 5656.
I had initially assumed that, since all of a user's per-connection
subdirectories live inside a top-level putty-connshare.$USER directory
that's not accessible to anyone else, there would be no need to
obfuscate the names of the internal directories for privacy, because
nobody would be able to look at them anyway.
Unfortunately, that's not true: 'netstat -ax' run by any user will
show up the full pathnames of Unix-domain sockets, including pathname
components that you wouldn't have had the access to go and look at
directly. So the Unix connection sharing socket names do need to be
obfuscated after all.
Since Unix doesn't have Windows's CryptProtectMemory, we have to do
this manually, by creating a file of random salt data inside the
top-level putty-connshare directory (if there isn't one there already)
and then hashing that salt with the "user@host" connection identifier
to get the socket directory name. What a pain.
[originally from svn r10222]
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
This is the same code I previously fixed for failing to check NULL
pointers coming back from ssh_pkt_getstring if the server's KEXINIT
ended early, leading to an embarrassing segfault in place of a fatal
error message. But I've now also had it pointed out to me that the
fatal error message passes the string as %s, which is inappropriate
because (being read straight out of the middle of an SSH packet) it
isn't necessarily zero-terminated!
This is still just an embarrassing segfault in place of a fatal error
message, and not exploitable as far as I can see, because the string
is passed to a dupprintf, which will either read off the end of
allocated address space and segfault non-exploitably, or else it will
find a NUL after all and carefully allocate enough space to format an
error message containing all of the previous junk. But still, how
embarrassing to have messed up the same code _twice_.
[originally from svn r10211]
We now expect that after the server has sent us CHANNEL_CLOSE, we
should not expect to see any replies to our outstanding channel
requests, and conversely after we have sent CHANNEL_CLOSE we avoid
sending any reply to channel requests from the server. This was the
consensus among implementors discussing the problem on ietf-ssh in
April 2014.
To cope with current OpenSSH's (and perhaps other servers we don't
know about yet) willingness to send request replies after
CHANNEL_CLOSE, I introduce a bug-compatibility flag which is detected
for every OpenSSH version up to and including the current 6.6 - but
not beyond, since https://bugzilla.mindrot.org/show_bug.cgi?id=1818
promises that 6.7 will also implement the new consensus behaviour.
[originally from svn r10200]
Martin Prikryl reports that it had the exact same bug as old OpenSSH
(insisting that RSA signature integers be padded with leading zero
bytes to the same length as the RSA modulus, where in fact RFC 4253
section 6.6 says it ought to have _no_ padding), but is recently
fixed. The first version string to not have the bug is reported to be
"mod_sftp/0.9.9", so here we recognise everything less than that as
requiring our existing workaround.
[originally from svn r10161]
If we search for a colon by computing ptr + host_strcspn(ptr,":"),
then the resulting pointer is always non-NULL, and the 'not found'
condition is not !p but !*p.
This typo could have caused PuTTY to overrun a string, but not in a
security-bug sense because any such string would have to have been
loaded from the configuration rather than received from a hostile
source.
[originally from svn r10123]
Both GUI PuTTY front ends have a piece of logic whereby a string is
interpreted as host:port if there's _one_ colon in it, but if there's
more than one colon then it's assumed to be an IPv6 literal with no
trailing port number. This permits the PuTTY command line to take
strings such as 'host', 'host:22' or '[::1]:22', but also cope with a
bare v6 literal such as '::1'.
This logic is also required in the two Plink front ends and in the
processing of CONF_loghost for host key indexing in ssh.c, but was
missing in all those places. Add it.
[originally from svn r10121]
I've gone through everywhere we handle host names / addresses (on
command lines, in PuTTY config, in port forwarding, in X display
names, in host key storage...) and tried to make them handle IPv6
literals sensibly, by using the host_str* functions I introduced in my
previous commit. Generally it's now OK to use a bracketed IPv6 literal
anywhere a hostname might have been valid; in a few cases where no
ambiguity exists (e.g. no :port suffix is permitted anyway)
unbracketed IPv6 literals are also acceptable.
[originally from svn r10120]
The line that resets st->pktin->length to cover only the semantic
payload of the SSH message was overwriting the modification to
st->pktin->length performed by the optional decompression step. I
didn't notice because I don't habitually enable compression.
[originally from svn r10103]
[r10070 == 9f5d51a4ac]
I've enabled gcc's format-string checking on dupprintf, by declaring
it in misc.h to have the appropriate GNU-specific attribute. This
pointed out a selection of warnings, which I've fixed.
[originally from svn r10084]
The basic strategy is described at the top of the new source file
sshshare.c. In very brief: an 'upstream' PuTTY opens a Unix-domain
socket or Windows named pipe, and listens for connections from other
PuTTYs wanting to run sessions on the same server. The protocol spoken
down that socket/pipe is essentially the bare ssh-connection protocol,
using a trivial binary packet protocol with no encryption, and the
upstream has to do some fiddly transformations that I've been
referring to as 'channel-number NAT' to avoid resource clashes between
the sessions it's managing.
This is quite different from OpenSSH's approach of using the Unix-
domain socket as a means of passing file descriptors around; the main
reason for that is that fd-passing is Unix-specific but this system
has to work on Windows too. However, there are additional advantages,
such as making it easy for each downstream PuTTY to run its own
independent set of port and X11 forwardings (though the method for
making the latter work is quite painful).
Sharing is off by default, but configuration is intended to be very
easy in the normal case - just tick one box in the SSH config panel
and everything else happens automatically.
[originally from svn r10083]
Now that it doesn't actually make a network connection because that's
deferred until after the X authorisation exchange, there's no point in
having it return an error message and write the real output through a
pointer argument. Instead, we can just have it return xconn directly
and simplify the call sites.
[originally from svn r10081]
Rather than the top-level component of X forwarding being an
X11Display structure which owns some auth data, it's now a collection
of X11FakeAuth structures, each of which owns a display. The idea is
that when we receive an X connection, we wait to see which of our
available auth cookies it matches, and then connect to whatever X
display that auth cookie identifies. At present the tree will only
have one thing in it; this is all groundwork for later changes.
[originally from svn r10079]
Now we wait to open the socket to the X server until we've seen the
authorisation data. This prepares us to do something else with the
channel if we see different auth data, which will come up in
connection sharing.
[originally from svn r10078]
I don't know that this can ever be triggered in the current state of
the code, but when I start mucking around with SSH session closing in
the near future, it may be handy to have it.
[originally from svn r10076]
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
Because the upcoming connection sharing changes are going to involve
us emitting outgoing SSH packets into our log file that we didn't
construct ourselves, we can no longer rely on metadata inserted at
packet construction time to tell us which parts of which packets have
to be blanked or omitted in the SSH packet log. Instead, we now have
functions that deal with constructing the blanks array just before
passing all kinds of packet (both SSH-1 and SSH-2, incoming and
outgoing) to logging.c; the blanks/nblanks fields in struct Packet are
therefore no longer needed.
[originally from svn r10071]
There's always been some confusion over exactly what it all means. I
haven't cleaned it up to the point of complete sensibleness, but I've
got it to a point where I can at least understand and document the
remaining non-sensibleness.
[originally from svn r10070]
It's now indexed by source hostname as well as source port (so that
separate requests for the server to listen on addr1:1234 and
addr2:1234 can be disambiguated), and also its destination host name
is dynamically allocated rather than a fixed-size buffer.
[originally from svn r10062]
Anthony Ho reports that this can occur naturally in some situation
involving Windows 8 + IE 11 and dynamic port forwarding: apparently we
get through the SOCKS negotiation, send our CHANNEL_OPEN, and then
*immediately* suffer a local WSAECONNABORTED error before the server
has sent back its OPEN_CONFIRMATION or OPEN_FAILURE. In this situation
ssh2_channel_check_close was failing to notice that the channel didn't
yet have a valid server id, and sending out a CHANNEL_CLOSE anyway
containing 32 bits of uninitialised nonsense.
We now handle this by turning our half-open CHAN_SOCKDATA_DORMANT into
a half-open CHAN_ZOMBIE, which means in turn that our handler
functions for OPEN_CONFIRMATION and OPEN_FAILURE have to recognise and
handle that case, the former by immediately initiating channel closure
once we _do_ have the channel's server id to do it with.
[originally from svn r10039]
CHAN_AGENT channels need c->u.a.message to be either NULL or valid
dynamically allocated memory, because it'll be freed by
ssh_channel_destroy. This bug triggers if an agent forwarding channel
is opened and closed without having sent any queries.
[originally from svn r10032]
We now only present the full set of host key algorithms we can handle
in the first key exchange. In subsequent rekeys, we present only the
host key algorithm that we agreed on the previous time, and then we
verify the host key by simply enforcing that it's exactly the same as
the one we saw at first and disconnecting rudely if it isn't.
[originally from svn r10027]
sitting on a pile of buffered data waiting for WINDOW_ADJUSTs, we
should throw away that buffered data, because the CHANNEL_CLOSE tells
us that we won't be receiving those WINDOW_ADJUSTs, and if we hang on
to the data and keep trying then it'll prevent ssh_channel_try_eof
from sending the CHANNEL_EOF which is a prerequisite of sending our
own CHANNEL_CLOSE.
[originally from svn r9953]
crWaitUntilV(pktin) with plain crReturnV, because those coroutines can
be called back either with a response packet from the channel request
_or_ with NULL by ssh_free meaning 'please just clean yourself up'.
[originally from svn r9927]
warnings about insecure crypto components. The latter may crReturn
(though not in any current implementation, I believe), which
invalidates pktin, which is used by the former.
[originally from svn r9921]
of the GET_32BIT macros and then used as length fields. Missing bounds
checks against zero have been added, and also I've introduced a helper
function toint() which casts from unsigned to int in such a way as to
avoid C undefined behaviour, since I'm not sure I trust compilers any
more to do the obviously sensible thing.
[originally from svn r9918]
since there is a theoretical code path (via the crReturn loop after
asking an interactive question about a host key or crypto algorithm)
on which we can leave and return to do_ssh1_login between allocating
and freeing those keys.
(In practice it shouldn't come up anyway with any of the current
implementations of the interactive question functions, not to mention
the unlikelihood of anyone non-specialist still using SSH-1, but
better safe than sorry.)
[originally from svn r9895]
as specified in RFC 6668. This is not so much because I think it's
necessary, but because scrypt uses HMAC-SHA-256 and once we've got it we
may as well use it.
Code very closely derived from the HMAC-SHA-1 code.
Tested against OpenSSH 5.9p1 Debian-5ubuntu1.
[originally from svn r9759]
RFC 4245 section 7.1 specifies the meaning of the "address to bind"
parameter in a "tcpip-forward" request. "0.0.0.0" and "127.0.0.1" are
specified to be all interfaces and the loopback interface respectively
in IPv4, while "" and "localhost" are the address-family-agnostic
equivalents. Switch PuTTY to using the latter, since it doesn't seem
right to force IPv4.
There's an argument that PuTTY should provide a means of configuring the
address family used for remote forwardings like it does for local ones.
[originally from svn r9668]
First, make absolute times unsigned. This means that it's safe to
depend on their overflow behaviour (which is undefined for signed
integers). This requires a little extra care in handling comparisons,
but I think I've correctly adjusted them all.
Second, functions registered with schedule_timer() are guaranteed to be
called with precisely the time that was returned by schedule_timer().
Thus, it's only necessary to check these values for equality rather than
doing risky range checks, so do that.
The timing code still does lots that's undefined, unnecessary, or just
wrong, but this is a good start.
[originally from svn r9667]
confused if they receive a request followed by immediate EOF, since we
currently send outgoing EOF as soon as we see the incoming one - and
then, when the response comes back from the real SSH agent, we send it
along anyway as channel data in spite of having sent EOF.
To fix this, I introduce a new field for each agent channel which
counts the number of calls to ssh_agentf_callback that are currently
expected, and we don't send EOF on an agent channel until we've both
received EOF and that value drops to zero.
[originally from svn r9651]
move the primary conditions out of them into their callers. Fixes a
crash in 'plink -N', since those functions would be called with a NULL
channel parameter and immediately dereference it to try to get c->ssh.
[originally from svn r9644]
They're only likely to be useful for freeing a coroutine state
structure, in which case there's no need to reset the line number
(since all such coroutines keep their line number in the state
structure) and the state structure pointer is always called "s".
[originally from svn r9632]
In sshfwd_unclean_close(), get ssh2_check_close() to handle sending
SSH_MSG_CHANNEL_CLOSE. That way, it can hold off doing so until any
outstanding channel requests are processed.
Also add event log message for unclean channel closures.
[originally from svn r9631]
crFinish or crFinishV, since they will attempt to write to the
coroutine state variable contained in that structure. Introduced some
new all-in-one macros crFinishFree and crFinishFreeV, and used those
instead. Should fix today's report of a crash just after authentication.
[originally from svn r9630]
Part the first: make sure that all structures describing channel
requests are freed when the SSH connection is freed. This involves
adding a means to ask a response handler to free any memory it holds.
Part the second: in ssh_channel_try_eof(), call
ssh2_channel_check_close() rather than emitting an SSH_MSG_CHANNEL_EOF
directly. This avoids the possibility of closing the channel while a
CHANNEL_REQUEST is outstanding.
Also add some assertions that helped with tracking down the latter
problem.
[originally from svn r9623]
This reduces code size a little and also makes it harder to
accidentally request a reply without putting in place a handler for
it or vice versa.
[originally from svn r9620]
The various setup routines can only receive CHANNEL_SUCCESS or
CHANNEL_FAILURE, so there's no need for the to worry about receiving
anything else. Strange packets will end up in do_ssh2_authconn
instead.
[originally from svn r9619]
Each of the minor start-of-session requests is now dealt with by its own
little co-routine, while the shell/command is done in do_ssh2_authconn()
itself. This eliminates one more round-trip in session setup: PuTTY gets
all the way up to sending a shell request before worrying about any
replies.
[originally from svn r9616]
Now each channel has a queue of arbitrary handlers for those messages,
with anything that sends a CHANNEL_REQUEST with want_reply true pushing
a new entry onto the queue, and a shared handler that dispatches
responses appropriately.
Currently, this is only used for winadj@putty.projects.tartarus.org, but
extending it to cover the initial requests as well shouldn't be too
painful.
[originally from svn r9615]
There's no need to have identical code generating server-to-client and
client-to-server versions of the cipher and MAC lists; a couple of
twice-around loops will do fine.
[originally from svn r9610]
Before, NULL in the dispatch table meant "send to the appropriate one of
do_ssh2_transport() and do_ssh2_authconn()". Now those (via small
shims) are specified directly in the dispatch table, so ssh2_protocol()
is much simpler.
In the process, this has somewhat centralised the handling of gross
server protocol violations. PuTTY will now disconnect with a rude
message when (e.g.) OpenSSH sends us an SSH_MSG_UNIMPLEMENTED when we
try to KEXINIT during authentication.
[originally from svn r9609]
by sending most of the initial SSH_MSG_CHANNEL_REQUEST messages before
waiting for any replies. The initial version of this code was a clever
thing with a two-pass loop, but that got hairy so I went for the simpler
approach of separating the request and reply code and having flags to
keep track of which requests have been sent.
[originally from svn r9599]
winadj@putty.projects.tartarus.org request. Not currently enabled
automatically, but should be usable as a manual workaround.
[originally from svn r9592]
zero but does it in such a way that over-clever compilers hopefully
won't helpfully optimise the call away if you do it just before
freeing something or letting it go out of scope. Use this for
(hopefully) every memset whose job is to destroy sensitive data that
might otherwise be left lying around in the process's memory.
[originally from svn r9586]
calling back->unthrottle), we should immediately call
ssh_process_queued_incoming_data to handle the SSH packets that have
been saved for later functioning while we were throttled. Otherwise,
they'll sit there unhandled until the next call to ssh_gotdata, which
might not be for ages if the server thinks it's waiting for us.
[originally from svn r9523]
already sent SSH2_MSG_CHANNEL_CLOSE, we should not skip the _whole_ of
sshfwd_unclean_close(), only the part about sending
SSH2_MSG_CHANNEL_CLOSE. It's still important to retag the SSH channel
as CHAN_ZOMBIE and clean up its previous data provider.
[originally from svn r9389]
subsidiary network modules like portfwd.c. To be called when the
subsidiary module experiences a socket error: it sends an emergency
CHANNEL_CLOSE (not just outgoing CHANNEL_EOF), and immediately deletes
the local side of the channel. (I've invented a new channel type in
ssh.c called CHAN_ZOMBIE, for channels whose original local side has
already been thrown away and they're just hanging around waiting to
receive the acknowledging CHANNEL_CLOSE.)
As a result of this and the last few commits, I can now run a port
forwarding session in which a local socket error occurs on a forwarded
port, and PuTTY now handles it apparently correctly, closing both the
SSH channel and the local socket and then actually recognising that
it's OK to terminate when all _other_ channels have been closed.
Previously the channel corresponding to the duff connection would
linger around (because of net_pending_errors never being called), and
keep being selected on (hence chewing CPU), and inhibit program
termination at the end of the session (because not all channels were
closed).
[originally from svn r9364]
for which we've already sent CHANNEL_CLOSE. It would be embarrassing
if the remote end had also sent CHANNEL_CLOSE in response and then
received our communication once it had forgotten about the channel.
[originally from svn r9360]
from forwarding data sources which will be good enough to last until
we close the socket, in the form of the override_throttle() functions.
So this finishes up the work in r9283, by manufacturing outgoing EOF
in response to incoming CLOSE on all channel types.
[originally from svn r9284]
[r9283 == c54e228d04]
incoming CHANNEL_CLOSE, if it's the main session channel. The idea is
that invocations such as 'plink -T hostname sh' (running a shell
without a remote pty) can be exited by typing 'exit' to the remote
shell, without plink blocking forever waiting for outgoing EOF.
I think it would be better to do the same for all other channel types
too, but that would need an extra API call which I haven't
implemented yet.
[originally from svn r9283]
backend should unilaterally assume outgoing EOF when it sees incoming
EOF, if and only if the main session channel is talking to a pty.
(Because ptys don't have a strong concept of EOF in the first place,
that seems like a sensible place to draw the line.) This fixes a bug
introduced by today's revamp in which if you used Unix Plink to run a
console session it would hang after you hit ^D - because the server
had sent EOF, but it was waiting for a client-side EOF too.
[originally from svn r9282]
data channels. Should comprehensively fix 'half-closed', in principle,
though it's a big and complicated change and so there's a good chance
I've made at least one mistake somewhere.
All connections should now be rigorous about propagating end-of-file
(or end-of-data-stream, or socket shutdown, or whatever) independently
in both directions, except in frontends with no mechanism for sending
explicit EOF (e.g. interactive terminal windows) or backends which are
basically always used for interactive sessions so it's unlikely that
an application would be depending on independent EOF (telnet, rlogin).
EOF should now never accidentally be sent while there's still buffered
data to go out before it. (May help fix 'portfwd-corrupt', and also I
noticed recently that the ssh main session channel can accidentally
have MSG_EOF sent before the output bufchain is clear, leading to
embarrassment when it subsequently does send the output).
[originally from svn r9279]
authentication. We should now produce an Event Log entry for every
authentication attempted and every authentication failure; meanwhile,
messages in the PuTTY window will not be generated for the failure of
auth types unless we also announced in the PuTTY window that we were
trying them. (GSSAPI was getting the latter wrong, leading to spurious
'Access denied' for many users of 0.61.)
[originally from svn r9226]
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
to "winadj@putty.projects.tartarus.org" with SSH_MSG_CHANNEL_SUCCESS despite
probably having no idea what it means, treat this just the same as
SSH_MSG_CHANNEL_FAILURE instead of killing the connection.
Tested only as far as making sure that winadj/FAILURE with a normal server
isn't _completely_ broken.
[originally from svn r9185]
[this svn revision also touched putty-wishlist]
Currently, if the IPC exchange goes wrong, the Event Log just prints
"Pageant is running. Requesting keys." and then goes on to the next
step without ever saying what happened.
[originally from svn r9177]
those in the CHAN_SOCKDATA_DORMANT state (i.e., local-to-remote forwardings
which the SSH server had not yet acknowledged).
Marcel Kilgus has been running with the ssh_do_close() patch for nearly two
years (*cough*) and reports that it has eliminated frequent
'unclean-close-crash' symptoms for him (due to the unclosed socket generating
a pfd_closing() which accessed freed memory), although I've not reproduced
that. The patch to ssh_free() is mine and not known to fix any symptoms.
[originally from svn r9069]
[this svn revision also touched putty-wishlist]
are now loaded from standard locations (system32 for SSPI, the
registry-stored MIT KfW install location for KfW) rather than using
the risky default DLL search path; I've therefore also added an
option to manually specify a GSS DLL we haven't heard of (which
should in principle Just Work provided it supports proper GSS-API as
specified in the RFC). The same option exists on Unix too, because
it seemed like too useful an idea to reserve to Windows. In
addition, GSSAPI is now documented, and also (unfortunately) its GUI
configuration has been moved out into a sub-subpanel on the grounds
that it was too big to fit in Auth.
[originally from svn r9003]
testing against NULL has already been dereferenced by the time we
bother to test it, so it's a bit pointless - and in any case, no
null pointer can come to this function from any existing call site.
[originally from svn r8990]
methods left to try, it's nice to have the version of that message
going to the client contain the list of methods sent by the server.
Saves a user having to pull it out of an SSH packet log.
[originally from svn r8981]
called 'pending_close'. This deals with the situation in which we're
forwarding a port, have received and locally buffered some data from
the local endpoint but not yet been able to pass it down the SSH
connection due to window limitations, and then the local endpoint
closes its socket. In this situation what we've been doing until now
is to immediately send SSH2_MSG_CHANNEL_CLOSE, causing the data
still in our local buffer to be lost; now we instead set the new
flag, which will remind us to send SSH2_MSG_CHANNEL_CLOSE _after_ we
empty our bufchain.
Should fix at least one manifestation of 'portfwd-close', though I
don't know if it's the cause of all the reports we've ever seen.
[originally from svn r8971]
reorganises the GSSAPI support so that it handles alternative
implementations of the GSS-API. In particular, this means PuTTY can
now talk to MIT Kerberos for Windows instead of being limited to
SSPI. I don't know for sure whether further tweaking will be needed
(to the UI, most likely, or to automatic selection of credentials),
but testing reports suggest it's now at least worth committing to
trunk to get it more widely tested.
[originally from svn r8952]
today reported an SSH2_MSG_UNIMPLEMENTED from a Cisco router which
looks as if it was triggered by SSH2_MSG_IGNORE, so I'm
experimentally putting this flag in. Currently must be manually
enabled, though if it turns out to solve the user's problem then
I'll probably add at least one version string...
[Edited commit message: actually, I also committed in error a piece
of experimental code as part of this checkin. Serve me right for not
running 'svn diff' first.]
[originally from svn r8926]
which we close the socket without destroying the channel. John
Peterson reports periodic crashes under heavy load which appear to
be fixed by this, though I don't know the exact circumstances
induced by that load.
[originally from svn r8871]
out, but are now just ignored.
(We should make more effort to prevent duplicates before they get as far as
ssh_setup_portfwd() -- it's currently trivially easy to enter them in the
GUI and on the command line, let alone both -- but there's bound to be someone
with a saved session containing dupes out there by now, and anyway there are
duplicates we can't detect before getting this far, for instance
"1234:localhost:22" vs "1234:localhost:ssh".)
[originally from svn r8623]
some servers (Debian in particular seems prone to this) send a k-i packet with
no prompts and nothing to display. We were printing an extra "Using
keyboard-interactive authentication" message in this case. (Introduced by me
in r8172, I think.)
[originally from svn r8492]
[r8172 == 211fdb9f46]
s->gss_sndtok in r8326. I'm not sure it was strictly necessary, since
even if there's no send token, gss_init_sec_context() is meant to explicitly
make it empty, but it wasn't an intentional change.
[originally from svn r8337]
[r8326 == 81dafd906e]
under SSH-2, don't risk looking at the length field of an incoming packet
until we've successfully MAC'ed the packet.
This requires a change to the MAC mechanics so that we can calculate MACs
incrementally, and output a MAC for the packet so far while still being
able to add more data to the packet later.
[originally from svn r8334]
ourselves, but on Unix then assumed it was compatible with the system's
gss_buffer_desc, which wasn't the case on LP64 systems. Now, on Unix
we make Ssh_gss_buf into an alias for gss_buffer_desc, though we keep
something similar to the existing behaviour on Windows. This requires
renaming a couple of the fields in Ssh_gss_buf, and hence fixing all
the references.
Tested on Linux (MIT Kerberos) and Solaris. Compiled on NetBSD (Heimdal).
Not tested on Windows because neither mingw32 nor winegcc worked out of the
box for me. I think the Windows changes are all syntactic, though, so
if this compiles it should work no worse than before.
[originally from svn r8326]
if we have no better ideas, with UI shamelessly stolen from Quest PuTTY.
Off by default, which effectively reverts the change to using the local
username by default that came in with GSSAPI support in r8138. Anyone wanting
seamless single sign-on will need to set the new option. (The previous
default behaviour was getting in the way in ad-hoc scenarios.)
Note that the PSCP and Unix-Plink behaviour of using the local username by
default have remained unchanged throughout; they are not affected by the new
option. Not sure if that's the Right Thing.
[originally from svn r8324]
[r8138 == de5dd9d65c]
strings more rigorously, and then we look up the local X authority
data in .Xauthority _ourself_ rather than delegating to an external
xauth program. This is (negligibly) more efficient on Unix, assuming
I haven't got it wrong in some subtle way, but its major benefit is
that we can now support X authority lookups on Windows as well
provided the user points us at an appropriate X authority file in
the standard format. A new Windows-specific config option has been
added for this purpose.
[originally from svn r8305]
both directions. We had a bug report yesterday about a Cisco router
sending SSH2_MSG_UNIMPLEMENTED and it wasn't clear for which packet;
logging the sequence numbers should make such problems much easier
to diagnose.
(In fact this logging fix wouldn't have helped in yesterday's case,
because the router also didn't bother to fill in the sequence number
field in the SSH2_MSG_UNIMPLEMENTED packet! This is a precautionary
measure against the next one of these problems.)
[originally from svn r8295]
no actual prompts, we weren't displaying the former, which was wrong. We
should now (although I haven't found a server to test it against).
[originally from svn r8172]
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]
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).
<http://msdn.microsoft.com/en-us/library/ms175782(VS.80).aspx>
[originally from svn r8030]
advertise so that the server can't exceed our maximum packet size.
Enable it for "1.36_sshlib GlobalSCAPE" which apparently sends oversize
packets otherwise.
[originally from svn r7804]
as well. This won't be triggered in the usual case, but it's useful
if the remote end ignores our window, or if we're in "simple" mode and
setting the window far larger than is necessary.
[originally from svn r7756]
spurious SSH_MSG_CHANNEL_FAILUREs, treat them as the protocol errors
they are and forcibly disconnect. Inspired by recent traffic on
comp.security.ssh.
[originally from svn r7752]
a single function which also handles checking that channels exist and
are properly open. This should make PuTTY a little less tolerant of
servers that send bogus messages.
[originally from svn r7751]
performance. The theory behind this is fairly simple, though the
implementation turns out to be a little trickier than it looks.
The basic idea is that when the connection isn't being limited by our ability
to process data, we want to ensure that the window size _as seen by the server_
never drops to zero. Measuring the server's view of the window size is done
by arranging for it to acknowledge every SSH_MSG_CHANNEL_WINDOW_ADJUST, or
rather an SSH_MSG_CHANNEL_REQUEST sent just before it. That way we can tell
when it its outgoing data stream it received the window adjustment, and
thus how small the server's view of the window got.
At present, we only ever increase the window size. In theory, we could
arrange to reduce it again if the server's view of it seemed to be persistently
too large, but my experiments suggest that getting this right will be tricky.
[originally from svn r7735]
for it. It's possible that this obsoletes BUG_CHOKES_ON_RSA. Certainly
the one SSH-1.5-Cisco-1.25 server I found was correctly not advertising RSA
auth. For now, leave it in, because I'm not feeling entirely confident.
[originally from svn r7726]
because it can ever be negative, but because we'll be comparing it with
another int. This way, C's promotion rules don't bite us and we should
stand slightly more chance of coping with broken servers that overrun our
window.
[originally from svn r7683]
and tweak ssh2_set_window() so it can cope with that. Also arrange to send
a private channel message in simple mode to tell the server that it can safely
use a large window too.
[originally from svn r7679]
channel, arrange to set the SSH-2 window size to something very
large. This prevents the connection stalling when the window fills
up, and means that PSCP receives data _much_ faster.
[originally from svn r7672]
used up, rather than over half. That this increases the throughput of PSCP
by 50% indicates just how broken our window handling is.
[originally from svn r7667]
arrange to handle usefully the case where the server sends us more data
than it's allowed to. There's no danger of overflow, since the maximum is
OUR_V2_WINSIZE and the minimum is -OUR_V2_MAXPKT (at least if the server is
nice).
[originally from svn r7661]
instead of a bitfield for both. This doesn't gain much here, but it should
make it easier to make things other than logging use the context.
[originally from svn r7647]
This allows us to send data in ssh_init(), albeit at the expense of its not
being properly logged, so arrange to send the version string then if that's
sensible, which should reduce the number of round-trips required to bring
up an SSH-2 connection.
[originally from svn r7646]
the SSH-2-only case, we can send it as soon as we connect rather than waiting
for the server's one. Unfortunately, actually doing so will take a little
more effort -- there are subtleties to do with having a working log context
at the right moment that need to be sorted out.
[originally from svn r7645]
Should be no significant change in behaviour.
(Well, entering usernames containing commas on Plink's command line will be
a little harder now.)
[originally from svn r7628]
remember to put an empty string in it rather than sending a completely
empty packet. This should help with those servers (notably RomSShell)
that actually check the contents of SSH_MSG_IGNORE.
[originally from svn r7236]
will close the window even in `close window only on clean exit'
mode. Also, while I'm here, arrange a suitable exit code for
"exit-signal".
[originally from svn r7121]
ability to easily re-enable the r5122 behaviour, in case we need to
conditionally switch between the two at a later date.
[originally from svn r7073]
[r5122 == 8a20515844]
[this svn revision also touched putty-wishlist]
(Since we choose to compile with -Werror, this is particularly important.)
I haven't yet checked that the resulting source actually compiles cleanly with
GCC 4, hence not marking `gcc4-warnings' as fixed just yet.
[originally from svn r7041]
BUG_NEEDS_SSH1_PLAIN_PASSWORD do exactly what it says on the tin, independent
of whether BUG_CHOKES_ON_SSH1_IGNORE is set.
This is invisible in the default configuration, as all servers marked as having
the second bug have the first one too, but it would allow one to manually
configure PuTTY to cope with a SSH-1 server that got upset by ignore messages
during authentication, but was fine with their use as keepalives.
[originally from svn r6876]
in an SSH connection _in addition_ to the decrypted packets. This
will hopefully come in useful for debugging wire data corruption
issues: you can strace the server, enable this mode in the client,
and compare the sent and received data.
I'd _like_ to have this mode also log Diffie-Hellman private
exponents, session IDs, encryption and MAC keys, so that the
resulting log file could be used to independently verify the
correctness of all cryptographic operations performed by PuTTY.
However, I haven't been able to convince myself that the security
implications are acceptable. (It doesn't matter that this
information would permit an attacker to decrypt the session, because
the _already_ decrypted session is stored alongside it in the log
file. And I'm not planning, under any circumstances, to log users'
private keys. But gaining access to the log file while the session
was still running would permit an attacker to _hijack_ the session,
and that's the iffy bit.)
[originally from svn r6835]