We also have the special-purpose -DUNPROTECT to disable just the ACL
changes, but if you want to compile without any Windows security API
support at all (e.g. experimentally building against winelib) then
it's easier not to have to specify both defines separately.
logevent() doesn't do printf-style formatting (though the logeventf
wrapper in ssh.c does), so if you need to format a message, it has to
be done separately with dupprintf.
By default Windows processes have wide open ACLs which allow interference
by other processes running as the same user. Adjust our ACL to make this
a bit harder.
Because it's useful to protect PuTTYtel as well, carve winsecur.c into
advapi functions and wincapi.c for crypt32 functions.
This is generated in response to the SendInput() Windows API call, if
that in turn is passed an KEYBDINPUT structure with KEYEVENTF_UNICODE
set. That method of input generation is used by programs such as
'WinCompose' to send an arbitrary Unicode character as if it had been
typed at the keyboard, even if the keyboard doesn't actually provide a
key for it.
Like VK_PROCESSKEY, this key code is an exception to our usual policy
of manually translating keystrokes: we handle it by calling
TranslateMessage, to get back the Unicode character it contains as a
WM_CHAR message.
(If that Unicode character in turn is outside the BMP, it may come
back as a pair of WM_CHARs in succession containing UTF-16 surrogates;
if so, that's OK, because the new Unicode WM_CHAR handler can cope.)
This causes WM_CHAR messages sent to us to have a wParam containing a
16-bit value encoded in UTF-16, rather than an 8-bit value encoded in
the system code page.
As far as I can tell, there aren't many other knock-on effects - e.g.
you can still interact with the window using ordinary char-based API
functions such as SetWindowText, and the Windows API will do the
necessary conversions behind the scenes. However, even so, I'm half
expecting some sort of unforeseen bug to show up as a result of this.
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
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.
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.
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]
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]
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 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]
This restores PuTTY's backward compatibility to versions of Windows
too old to have ToUnicodeEx in their system libraries, which was
accidentally broken in 0.63.
[originally from svn r10061]
A couple of users report that my recent reworking of the Windows
top-level message loop has led to messages occasionally being lost,
and MsgWaitForMultipleObjects blocking when it ought to have been
called with a zero timeout. I haven't been able to reproduce this
myself, but according to one reporter, PeekMessage(PM_NOREMOVE) is
effective at checking for a non-empty message queue in a way that
GetQueueStatus is not. Switch to using that instead. Thanks to Eric
Flumerfelt for debugging and testing help.
[originally from svn r10057]
Jochen Erwied points out that once you've used PeekMessage to remove
_one_ message from the message queue, MsgWaitForMultipleObjects will
consider the whole queue to have been 'read', or at least looked at
and deemed uninteresting, and so it will block until a further message
comes in. Hence, my change in r10040 which stops us from looping on
PeekMessage until the queue is empty has the effect of causing the
rest of the message queue not to be acted on until a new message comes
in to unblock it. Fix by checking if the queue is nonempty in advance
of calling MsgWaitForMultipleObjects, and if so, giving it a zero
timeout just as we do if there's a pending toplevel callback.
[originally from svn r10052]
[r10040 == 5c4ce2fadf]
This change attempts to reinstate as a universal property something
which was sporadically true of the ad-hockery that came before
toplevel callbacks: that if there's a _very long_ queue of things to
be done through the callback mechanism, the doing of them will be
interleaved with re-checks of other event sources, which might (e.g.)
cause a flag to be set which makes the next callback decide not to do
anything after all.
[originally from svn r10040]
It was one of those things that went in ages ago on Windows and never
got replicated in the Unix front end. And it needn't be: ldisc.c is a
perfect place to put it, since it knows which of the data it's sending
is based on a keystroke and which is automatically generated, and it
also has access to the terminal context. So now a keypress can
interrupt a runaway paste on all platforms.
[originally from svn r10025]
Again, I've removed the special-purpose ad-hockery from the assorted
front end message loops that dealt with deferred handling of socket
errors, and instead uxnet.c and winnet.c arrange that for themselves
by calling the new general top-level callback mechanism.
[originally from svn r10023]
Instead of setting a must_close_session flag and having special code
in the message loop to check it, we'll schedule the call to
close_session using the new top-level callback system.
[originally from svn r10021]
I've removed the ad-hoc front-end bodgery in the Windows and GTK ports
to arrange for term_paste to be called at the right moments, and
instead, terminal.c itself deals with knowing when to send the next
chunk of pasted data using a combination of timers and the new
top-level callback mechanism.
As a happy side effect, it's now all in one place so I can actually
understand what it's doing! It turns out that what all that confusing
code was up to is: send a line of pasted data, and delay sending the
next line until either a CR or LF is returned from the server
(typically indicating that the pasted text has been received and
echoed) or 450ms elapse, whichever comes first.
[originally from svn r10020]
This is a little like schedule_timer, in that the callback you provide
will be run from the top-level message loop of whatever application
you're in; but unlike the timer mechanism, it will happen
_immediately_.
The aim is to provide a general way to avoid re-entrance of code, in
cases where just _doing_ the thing you want done is liable to trigger
a confusing recursive call to the function in which you came to the
decision to do it; instead, you just request a top-level callback at
the message loop's earliest convenience, and do it then.
[originally from svn r10019]
PuTTY does not trim a colon suffix off the hostname if it contains
_more than one_ colon. This allows IPv6 literals to be entered.
(Really we need to do a much bigger revamp of all uses of hostnames to
arrange that square-bracketed IPv6 literals work consistently, but
this at least removes a regression over 0.62.)
[originally from svn r9983]
[r9214 == a1f3b7a358]
palette_set() to be bogus. Fortunately, this isn't exploitable through
the terminal emulator, because the palette escape sequence parser
contains its own bounds check before even calling palette_set().
While I'm at it, fix the same goof in the OS X version! That port is
more or less abandoned, but that's no excuse for leaving obviously
wrong code lying around.
[originally from svn r9965]
The most interesting one is printer_add_enum, which I've modified to
take a char ** rather than a char * so that it can both realloc its
input buffer _and_ return NULL to indicate error.
[originally from svn r9959]
ToAsciiEx, where possible.
This enables support for keys which generate Unicode characters that
aren't in the system code page, which seems to me like a perverse way
for Windows to have set up the system code page but apparently does
happen, e.g. (I'm told) U+0219 and U+021B on Romanian keyboards.
Patch mostly due to Andrei Damian-Fekete.
[originally from svn r9942]
that the user really ought to know but that are not actually fatal to
continued operation of PuTTY or a single network connection.
[originally from svn r9932]
use 32-bit scrollbar position data instead of being limited to the
16-bit version that comes in scrollbar messages' wParam.
[originally from svn r9720]
mistakenly rearranged the logic in an if statement in window.c, with
the effect that scroll-wheel events are no longer sent via xterm mouse
tracking. Put it back to the way it was.
[originally from svn r9679]
[r9214 == a1f3b7a358]
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]
sequence: since init_fonts sets up ucsdata based on the available
Windows fonts, we should call it before passing ucsdata to term_init.
[originally from svn r9527]
the offset horizontal line characters in the VT100 line-drawing set
(o,p,r,s), so that no trace of it - and hence no pointless performance
hit - is compiled into the cross-platform modules on non-Windows
platforms.
[originally from svn r9467]
UTF-16 support. High Unicode characters in the terminal are now
converted back into surrogates during copy and draw operations, and
the Windows drawing code takes account of that when splitting up the
UTF-16 string for display. Meanwhile, accidental uses of wchar_t have
been replaced with 32-bit integers in parts of the cross-platform code
which were expecting not to have to deal with UTF-16.
[originally from svn r9409]
so we should ensure we treat it the same way as other WM_SIZEs that
show up during that time: set the width and height in conf, and set
the flag to have that width and height enacted on WM_EXITSIZEMOVE.
Fixes a bug in which dragging a PuTTY window directly from the Win7
snapped-to-half-screen position to the snapped-to-maximised state
would leave the terminal in the pre-snapped size.
[originally from svn r9404]
allocated type.
The main reason for this is to stop it from taking up a fixed large
amount of space in every 'struct value' subunion in conf.c, although
that makes little difference so far because Filename is still doing
the same thing (and is therefore next on my list). However, the
removal of its arbitrary length limit is not to be sneezed at.
[originally from svn r9314]
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]
(In an embarrassingly silly way, too. No end of difficult stuff about
Conf serialisation done with great care and working just fine, and
then a trivial goof in using sscanf lets the whole lot down.)
[originally from svn r9237]
'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]
that we won't keep calling close_session() again the next time we go
round the message loop. Should fix unclean-close-hang. Thanks to Simon
Coleman for debugging.
[originally from svn r9115]
rectangle into smaller ones: it doesn't work any more, since the new
variable-pitch code can now call general_textout() with a larger
clipping rectangle than the text it's meant to be displaying. Instead,
general_textout() now uses the same semantics as the next loop up in
do_text_internal(): the first piece of text it displays uses the
opacity setting passed in, which blanks the entire clipping rectangle
if necessary, and then subsequent overlays are non-opaque. And the
same clipping rectangle is used throughout.
[originally from svn r9067]
array to ExtTextOut:
- move it inside the new big loop (this should fix a potential bug
whereby the DBCS handling altered some elements of it but the loop
did not actually step along it)
- initialise it more sensibly
- rename it to lpDx rather than IpDx, since as far as I can tell the
latter name was derived from a misreading of the former in the
Windows API docs.
[originally from svn r9066]