Previously only Unix front ends bothered to include it, on the basis
that only the pty backend needed it (to set IUTF8 in the pty). We're
about to need it everywhere else too.
It's really only useful with MinGW rather than a Cygwin toolchain these
days, as recent versions of the latter insist against linking with the
Cygwin DLL.
(I think it may no longer be possible to build with Cygwin out of the
box at all these days, but I'm not going to say so without having
actually checked that's the case. Settle for listing MinGW first in
various comments and docs.)
I've just upgraded my build environment to the latest Inno Setup
(apparently fixing some DLL hijacking issues), and found that the
build script doesn't run any more because the name of the output file
has changed - it used to produce Output/setup.exe, but now it produces
Output/mysetup.exe.
Rather than just fixing the build script to expect the new name, I've
explicitly specified an output filename of my own choice in putty.iss,
so that the build script should now work with versions before and
after the change.
I can't believe this codebase is around 20 years old and has had
multiple giant const-fixing patches, and yet there are _still_ things
that should have been const for years and aren't.
Ahem. Cut-and-paste goof that I introduced in commit 2eb952ca3, when I
moved the application names out of separate text controls in the
resource-file dialog descriptions.
Blocking PROCESS_QUERY_INFORMATION access to the process turned out to
stop screen readers like Microsoft Narrator from reading parts of the
PuTTY window like the System Menu.
strcspn() returns a size_t, which is not safe to pass as the parameter
in a printf argument list corresponding to a "*" field width specifier
in the format string, because the latter should be int, which may not
be the same size as size_t.
We were calling Windows file-handling API functions GetFilesize and
SetFilePointer, each of which returns two halves of a large integer by
writing the high half through a pointer, with pointers to the wrong
integer types. Now we're always passing the exact type defined in the
API, and converting after the fact to our own uint64 type, so this
should avoid any risk of wrong-sized pointers.
These integer types are correct for the id/handle parameter to
AppendMenu / InsertMenu / DeleteMenu, and also for the return type of
dialog box procedures.
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.
The old README.txt instructed you to manually update PATH if you
wanted to run pscp from a command prompt. But the MSI installer can do
that automatically, so the wording needs tweaks. And now that we're
actually launching README (at least optionally) from the installer UI,
it's more important to not make it look silly.
This is a thing that the Inno Setup installer did, and that I didn't
get round to replicating when I rushed out the initial MSI in a hurry.
I've checked that this doesn't prevent unattended installation by
administrators: running 'msiexec /q /i putty-whatever.msi' as
administrator still installs silently after this change, without
popping up the README unexpectedly on anyone's desktop as a side
effect.
(I _think_ - but I'm still a long way from an MSI expert - that that's
because /q turns off the whole UI part of the MSI system, and the
loading of README is actually triggered by the transition away from
the final UI dialog box, which we now never visit in the first place.)
I rushed out the MSI in too much of a hurry to sort out this kind of
thing, but now we've got leisure to reconsider, I think it's better
behaviour not to clutter everyone's desktops unless specifically asked
to.
It's only a warning; Windows PuTTYgen puts it up as a message box, and
will still generate the key if you click yes, and Unix PuTTYgen just
prints the warning and gets on with generation anyway. But it might
help encourage people to move away from 1024-bit keys, if they're
still using them.
Protecting our processes from outside interference need not be limited
to just PuTTY: there's no reason why the other SSH-speaking tools
shouldn't have the same treatment (PSFTP, PSCP, Plink), and PuTTYgen
and Pageant which handle private key material.
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.
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.
This is an absolutely horrible piece of code, relying not only on font
metrics but also on an observed correlation between the length of a
key algorithm name and whether or not it needs a separate key size
displayed. But it'll do for the moment, and it's less effort than
writing a custom piece of Windows API code to display the list box
entries in a properly robust way :-(
Jacob pointed out that a free-text field for entering a key size in
bits is all very well for key types where we actually _can_ generate a
key to a size of your choice, but less useful for key types where
there are only three (or one) legal values for the field, especially
if we don't _say_ what they are.
So I've revamped the UI a bit: now, in ECDSA mode, you get a dropdown
list selector showing the available elliptic curves (and they're even
named, rather than just given by bit count), and in ED25519 mode even
that disappears. The curve selector for ECDSA and the bits selector
for RSA/DSA are independent controls, so each one remembers its last
known value even while temporarily hidden in favour of the other.
The actual generation function still expects a bit count rather than
an actual curve or algorithm ID, so the easiest way to actually
arrange to populate the drop-down list was to have an array of bit
counts exposed by sshecc.c. That's a bit ugly, but there we go.
One small functional change: if you enter an absurdly low value into
the RSA/DSA bit count box (under 256), PuTTYgen used to give a warning
and reset it to 256. Now it resets it to the default key length of
2048, basically because I was touching that code anyway to change a
variable name and just couldn't bring myself to leave it in a state
where it intentionally chose such an utterly useless key size. Of
course this doesn't prevent generation of 256-bit keys if someone
still really wants one - it just means they don't get one selected as
the result of a typo.
It would be nicer if we could also make this show up as the icon for
the .msi file itself when viewed in Explorer, but apparently nothing
can change that. But at least this still gives us _some_ use for the
cardboard-box icon :-)
Mostly this is a reaction to the reports of Inno Setup having a DLL
hijacking vulnerability. But also, the new installer has several other
nice features that our Inno Setup one didn't provide: it can put the
PuTTY install directory on PATH automatically, and it supports
completely automatic and silent install/uninstall via 'msiexec /q'
which should make it easier for sysadmins to roll out installation in
large organisations. Also, it just seems like good sense to be using
Windows's own native packaging system (or closest equivalent) rather
than going it alone.
(And on the developer side, I have to say I like the fact that WiX
lets me pass in the version number as a set of command-line #define-
equivalents, whereas for Inno Setup I had to have Buildscr apply Perl
rewriting to the source file.)
For the moment, I'm still building the old Inno Setup installer
alongside this one, but I expect to retire it once the WiX one has
survived in the wild for a while and proven itself more or less
stable.
I've found both MSI and WiX to be confusing and difficult
technologies, so this installer has some noticeable pieces missing
(e.g. retrospective reconfiguration of the installed feature set, and
per-user vs systemwide installation) simply because I couldn't get
them to work. I've commented the new installer source code heavily, in
the hope that a passing WiX expert can give me a hand!
A user reported in January that locking down our process ACL causes
get_user_sid's call to OpenProcessToken to fail with a permissions
error. This _shouldn't_ be important, because we'll already have found
and cached the user SID before getting that far - but unfortunately
the call to get_user_sid in winnpc.c was bypassing the cache and
trying the whole process again.
This fix changes the memory ownership semantics of get_user_sid():
it's now an error to free the value it gives you, or else the *next*
call to get_user_sid() will return a stale pointer. Hence, also
removed those frees everywhere they appear.
Now all the uses of the licence text or the short copyright notice get
it from a new header "licence.h", which in turn is built by a Perl
script licence.pl invoked by mkfiles.pl, using LICENCE itself as the
source.
Hence, I can completely remove a whole section from the list of
licence locations in CHECKLST.txt :-)
(cherry picked from commit 9ddd071ec2)
Conflicts:
unix/gtkdlg.c
windows/winpgnt.c
(cherry-picker's notes: one conflict was just changed context, the
other was deleting a copy of the licence that wasn't quite the same
between branches)
This makes the About and Licence boxes copy-and-pasteable, similarly
to what I've just done on Unix.
(But unlike on the Unix side, here I haven't touched the host key
prompt dialog, because that's a standard Windows MessageBox and not
easy to mess around with. Plus, in any case, you can already hit ^C to
copy the whole text out of a MessageBox. Same goes for the PGP
fingerprints dialog.)
As a side effect, several copies of the copyright notice and licence
text have moved from .rc files into C source. I've updated
CHECKLST.txt, but they won't stay there for long.
(cherry picked from commit 2eb952ca31)
Conflicts:
windows/pageant.rc
windows/puttygen.rc
windows/win_res.rc2
(cherry-picker's notes: the conflict was just because several copies
of the licence text were deleted, and they weren't quite the same
between branches)
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.
(cherry picked from commit 1659cf3f14)
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.
(cherry picked from commit 48db456801)
Conflicts:
Recipe
(cherry-picker's note: the conflict was just some context not looking
quite the same)
make_private_security_descriptor and a new function protectprocess().
protectprocess() opens the running PuTTY process and adjusts the
Everyone and user access control entries in its ACL to deny a
selection of permissions which malicious processes running as the same
user could use to hijack PuTTY.
(cherry picked from commit aba7234bc1)
TOOLTYPE_NONNETWORK (i.e. pterm) already has "-log" (as does Unix
PuTTY), so there's no sense suppressing the synonym "-sessionlog".
Undocumented lacunae that remain:
plink accepts -sessionlog, but does nothing with it. Arguably it should.
puttytel accepts -sshlog/-sshrawlog (and happily logs e.g. Telnet
negotiation, as does PuTTY proper).
(cherry picked from commit a454399ec8)
Conflicts:
unix/uxplink.c
windows/winplink.c
(cherry-picker's notes: the conflict was only contextual, in the Plink
help output)
Now all the uses of the licence text or the short copyright notice get
it from a new header "licence.h", which in turn is built by a Perl
script licence.pl invoked by mkfiles.pl, using LICENCE itself as the
source.
Hence, I can completely remove a whole section from the list of
licence locations in CHECKLST.txt :-)
This makes the About and Licence boxes copy-and-pasteable, similarly
to what I've just done on Unix.
(But unlike on the Unix side, here I haven't touched the host key
prompt dialog, because that's a standard Windows MessageBox and not
easy to mess around with. Plus, in any case, you can already hit ^C to
copy the whole text out of a MessageBox. Same goes for the PGP
fingerprints dialog.)
As a side effect, several copies of the copyright notice and licence
text have moved from .rc files into C source. I've updated
CHECKLST.txt, but they won't stay there for long.
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.