It's all very well for these two different formats to share a type
code as long as we're only loading them and not saving, but as soon as
we need to save one or the other, we'll need different type codes
after all.
This commit introduces the openssh_new_write() function, but for the
moment, it always returns failure.
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.
When a winhandl.c input thread returns EOF to the main thread, the
latter might immediately delete the input thread's context. I
carefully wrote in a comment that in that case we had to not touch ctx
ever again after signalling to the main thread - but the test for
whether that was true, which also touched ctx, itself came _after_ the
SetEvent which sent that signal. Ahem.
Spotted by Minefield, which it looks as if I haven't run for a while.
I had set up an event object for signalling incoming connections to
the named pipe, and then called handle_add_foreign_event to get that
event object watched for connections - but when I closed down the
listening pipe, I deleted the event object without also cancelling
that foreign-event handle, so that winhandl.c would potentially call
the callback for a destroyed object.
This was an old bug, fixed around 0.59, which apparently regressed
when I rewrote the main event loop using the toplevel_callback
mechanism.
Investigation just now suggests that it has to do with my faulty
assumption that Windows PeekMessage would deliver messages in its
message queue in FIFO order (i.e. that the thing calling itself a
message queue is actually a _queue_). In fact my WM_NETEVENT seems to
like to jump the queue, so that once a steady stream of them starts
arriving, we never do anything else in the main event loop (except
deal with handles).
Worked around in a simple and slightly bodgy way, namely, we don't
stop looping on PeekMessage and run our toplevel callbacks until we've
either run out of messages completely or else seen at least one that
_isn't_ a WM_NETEVENT. That way we should reliably interleave NETEVENT
processing with processing of other stuff.
To understand the handle leak bug that I fixed in git commit
7549f2da40, I had to think fairly hard
to remind myself what all this code was doing, which means the
comments weren't good enough. Expanded and rewritten some of them in
the hope that things will be clearer next time.
If (say) a read handle returns EOF, and its gotdata function responds
by calling handle_free(), then we want the handle to have already had
its defunct flag set so that the handle can be destroyed. Otherwise
handle_free will set the 'done' flag to ask the subthread to
terminate, and then sit and wait for it to say it's done so -
forgetting that it signalled termination already by returning EOF, and
hence will not be responding to that signal.
Ditto for write errors on write handles, though that should happen
less often.
The code for cleaning up handle structures works by the main thread
asking the per-handle subthread to shut down by means of setting its
'done' flag, and then once the subthread signals back through its
event object that it's done so, the main thread frees all its
resources and removes the event object from the list of things being
checked in the program's event loop.
But read threads were not sending back that final event acknowledging
a request to shut down, so their event objects were never being
cleaned up.
Bug spotted by Ronald Weiss.
We were checking the return value of CreateThread for validity, but
not keeping it to free afterwards if it _was_ valid. Also, we weren't
closing ctx->event in the valid case either. Patch due to Tim Kosse.
I don't think anyone has ever actually called it that, colloquially
_or_ formally, and if anyone ever did (in a bug report, say) I'd
probably have to stop and think to work out what they meant. It's
universally called Plink, and should be officially so as well :-)
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.
If (Msg)WaitForMultipleObjects returns WAIT_TIMEOUT, we expect 'next'
to have been initialised. This can occur without having called
run_timers(), if a toplevel callback was pending, so we can't expect
run_timers to have reliably initialised 'next'.
I'm not actually convinced this could have come up in either of the
affected programs (Windows PSFTP and Plink), due to the list of things
toplevel callbacks are currently used for, but it certainly wants
fixing anyway for the future.
Spotted by Coverity.
Pageant's list box needs its tab stops reorganised a little for new
tendencies in string length, and also has to cope with there only
being one prefix space in the output of the new string fingerprint
function. PuTTYgen needs to squash more radio buttons on to one line.
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.
The OpenSSH key importer and exporter were structured in the
assumption that the strong commonality of format between OpenSSH RSA
and DSA keys would persist across all key types. Moved code around so
it's now clear that this is a peculiarity of those _particular_ two
key types which will not apply to others we add alongside them.
Also, a boolean 'is_dsa' in winpgen.c has been converted into a more
sensible key type enumeration, and the individually typed key pointers
have been piled on top of each other in a union.
This is a pure refactoring change which should have no functional
effect.
I've shifted away from using the SVN revision number as a monotonic
version identifier (replacing it in the Windows version resource with
a count of days since an arbitrary epoch), and I've removed all uses
of SVN keyword expansion (replacing them with version information
written out by Buildscr).
While I'm at it, I've done a major rewrite of the affected code which
centralises all the computation of the assorted version numbers and
strings into Buildscr, so that they're all more or less alongside each
other rather than scattered across multiple source files.
I've also retired the MD5-based manifest file system. A long time ago,
it seemed like a good idea to arrange that binaries of PuTTY would
automatically cease to identify themselves as a particular upstream
version number if any changes were made to the source code, so that if
someone made a local tweak and distributed the result then I wouldn't
get blamed for the results. Since then I've decided the whole idea is
more trouble than it's worth, so now distribution tarballs will have
version information baked in and people can just cope with that.
[originally from svn r10262]
The winegcc hack I use for my Coverity builds is currently using a
version of wincrypt.h that's missing a couple of constants I use.
Ensure they're defined by hand, but (just in case I defined them
_wrong_) also provide a command-line define so I can do that only in
the case of Coverity builds.
[originally from svn r10234]
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]
A user points out that the person who writes a REG_SZ into the
registry can choose whether or not to NUL-terminate it properly, and
if they don't, RegQueryValueEx will retrieve it without the NUL. So if
someone does that to PuTTY's saved session data, then PuTTY may
retrieve nonsense strings.
Arguably this is the fault of whoever tampered with the saved session
data without doing it the same way we would have, but even so, there
ought to be some handling at our end other than silently returning the
wrong data, and putting the NUL back on seems more sensible than
complaining loudly.
[originally from svn r10215]
The IDM_RECONF handler unconditionally calls ldisc_configure to
reconfigure the line discipline for the new echo/edit settings, but in
fact ldisc can be NULL if no session is currently active. (Indeed, the
very next line acknowledges this, by testing it for NULL before
calling ldisc_send!) Thanks to Alexander Wong for the report.
[originally from svn r10214]
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]
Philippe Maupertuis reports that on one particular machine, Windows
causes the named pipe created by upstream PuTTY to be owned by the
Administrators group SID rather than the user's SID, which defeats the
security check in the downstream PuTTY. No other machine has been
reported to do this, but nonetheless it's clearly a thing that can
sometimes happen, so we now work around it by specifying explicitly in
the security descriptor for the pipe that its owner should be the user
SID rather than any other SID we might have the right to use.
[originally from svn r10188]
winshare.c includes ssh.h, but if you defined NO_SECURITY it then
decides to fall back to including the stub noshare.c, which includes
ssh.h again. Fix by moving a block of includes inside the ifdef.
[originally from svn r10184]
On Windows (X mouse reporting of the mouse wheel isn't currently done
by the Unix front end, though I'm shortly about to fix that too) a
mouse wheel event is translated into a virtual button, and we send
both a press and a release of that button to terminal.c, which encodes
both in X mouse reporting escape sequences and passes them on to the
server. This isn't consistent with what xterm does - scroll-wheel
events are encoded _like_ button presses, but differ semantically in
that they don't have matching releases. So we're updating to match
xterm.
[originally from svn r10138]
There's been a long-standing FIXME in Windows's sk_newlistener which
says that in IPv6 mode, an explicit source address (e.g. from a
command-line option of the form -L srcaddr:12345:dest:22) is ignored.
Now it's honoured if possible.
[originally from svn r10122]
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]
Mike Edenfield points out that modern versions of the Windows SDK have
decided that 'INPUT' is a sensible name for an OS data structure
(sigh), and provided a patch to add a disambiguating prefix to
winhandl.c's enum values INPUT, OUTPUT and FOREIGN.
[originally from svn r10109]
Daniel Meidlinger reports that at least one Windows machine which is
not obviously otherwise misconfigured will respond to our
SetEntriesInAcl call with odd errors like ERROR_NONE_MAPPED or
ERROR_TRUSTED_RELATIONSHIP_FAILURE. This is apparently to do with
failure to convert the names "EVERYONE" and "CURRENT_USER" used in the
ACL specification to SIDs. (Or perhaps only one of them is the problem
- I didn't investigate in that direction.)
If we instead construct a fully SID-based ACL, using the well-known
world SID in place of EVERYONE and calling our existing get_user_sid
routine in place of CURRENT_USER, he reports that the problem goes
away, so let's do that instead.
While I'm here, I've slightly simplified the function prototype of
make_private_security_descriptor(), by turning 'networksid' into an
internal static that we can reuse in subsequent calls once we've set
it up. (Mostly because I didn't fancy adding another two pointless
parameters at every call site for the two new SIDs.)
[originally from svn r10096]