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]