The callback function to pageant_enum_keys now takes a flags
parameter, which receives the flags word from the extended key list
request, if available. (If not, then the flags word is passed as
zero.)
The only callback that uses this parameter is the one for printing
text output from 'pageant -l', which uses it to print a suffix on each
line, indicating whether the key is stored encrypted only (so it will
need a passphrase on next use), or whether it's stored both encrypted
_and_ unencrypted (so that 'pageant -R' will be able to return it to
the former state).
Now, if you have a given key stored encrypted in your agent and you
say 'pageant -a [same key]' (without -E), Pageant will notice (via the
new extended key list request) that the key is currently encrypted in
the agent, and that you're trying to add it unencrypted. In this
situation it won't abort the attempt, and will try to add the key
anyway, so that it becomes decrypted in your agent.
Now, if you send SSH2_AGENTC_ADD_IDENTITY with a cleartext private key
blob, and the agent already contains an encrypted-only version of the
same key, it will drop the cleartext version in alongside it,
effectively decrypting the key as if the passphrase had been typed.
This is an extended version of SSH2_AGENTC_REQUEST_IDENTITIES, which
augments each entry in the returned key list with an extra field
containing additional data about the key.
The initial contents of that extra field are a pair of flags
indicating whether the key is currently stored in the agent encrypted,
decrypted or both.
The idea is that this will permit a Pageant-aware client to make
decisions based on that. For a start, the output key list can mention
it to the user; also, if you try to add a key unencrypted when it's
already present, we can discriminate based on whether it's already
present _unencrypted_
Somehow it had acquired a lot of internal 2-space indentation, which
is out of step with the rest of this code base's style. Before I get
into making more changes in here, let's clean it up.
When I added the psusan man page, I noticed that they've all got
impenetrable names like 'man-pl.but' to fit within 8.3 naming. But
this source base hasn't had to worry about 8.3 naming conventions in a
long time, so I think I can safely rename all those files to ones
whose purpose is more obvious.
I've been collecting actual examples of things I've used psusan for,
and now I think I have enough of them to make some kind of case for
why it's a useful tool. So I've written a man page, and dumped all my
collected examples in there.
In some applications of psusan, it's useful to establish a fixed
listening endpoint on a Unix-domain socket. You can make this happen
using an external helper program (effectively behaving like a
specialised inetd), but it's more convenient to have it built in to
psusan itself, and not really very difficult since Uppity had all the
necessary code already.
I've also added the --listen-once option from Uppity, and for good
measure, the --verbose option (so that psusan in listening mode can
show connections and disconnections on its original standard error).
'Uppity' is the name of a program that's only useful for debugging, so
I'd rather not have its name reused by psusan which I'm polishing up
to be actually useful to end users (if rather specialist ones).
So SshServerConfig now has an 'application name' field which is used
as the application name in the SSH banner, and Uppity sets it to
"Uppity" while psusan sets it to "PSUSAN".
This occurred to me recently as a (very small) hole in the logging
strategy: if the size of an allocated memory block depended on some
secret data, it certainly would change the control flow and memory
access pattern inside malloc, but since we disable logging inside
malloc, the log file from this test suite would never see the
difference.
Easily fixed by printing the size of each block in the code that
intercepts malloc and realloc. As expected, no test actually fails as
a result of filling in this gap.
On AArch64, there are unexpectedly malloc and free functions in ld.so,
so the module-load function finds them there, wraps them, and then
misses the real versions in libc.
This allows my side-channel test system to at least _compile_ on other
architectures without failing for the lack of OP_xxx enum constants,
although it now won't log all the things it needs to be a proper test.
Apart from being pointless, it also triggers a bug in OpenSSH pre-8.1
that causes it to send a repeat EXT_INFO after the rekey concludes,
which trips our quite draconian check for whether EXT_INFO has been
sent at the right time.
The OpenSSH bug: https://bugzilla.mindrot.org/show_bug.cgi?id=2929
Again in the GDK Broadway backend, where we never get a non-Unicode
translation of any keystroke: when we come to the code that handles
Ctrl+letter (and other symbols), we were basing the Ctrl transform on
output[1], that is, the non-Unicode translation we had so far. But we
didn't have one.
Now we check the use_ucsoutput flag to decide which of output and
ucsoutput to start from, and as a result, Ctrl+keys works again on
Broadway.
When you run using the GDK Broadway backend, this turns out to happen,
and it's new in my experience - I was cheerfully iterating over
event->string and calling strlen on it without ever checking it for
NULL.
I must have not recompiled with debug printouts enabled since updating
the internal printf functions to have the gcc printf attribute, or
these warnings would surely have come up before.
If it's worth having command-line options to _specify_ a log file,
it's also worth having options to avoid having to answer an
interactive prompt _about_ that log file every time.
(Particularly useful when debugging, in which I often want to run a
zillion instances of the same quite temporary command line that
involves writing a log file.)
This adds the framework to be able to send it in both client _and_
server (in the post-NEWKEYS slot); it's just that currently only the
server has anything it wants to put in it.
Uppity now announces its public key type list, which is enough by
itself to allow it to accept RFC 8332 rsa-sha2-* signatures during
userauth. (Because the key verification code receives an ssh-rsa host
key and validates it against the SHA2-based key algorithm structure
derived from the id string that was sent separately.)
The information was already centralised in find_pubkey_alg, but that
had a query-based API that couldn't enumerate the key types. Now I
expose an underlying array so that it's possible to iterate over them.
Also, I'd forgotten to add the two new rsa-sha2-* algorithms to
find_pubkey_alg. That's also done as part of this commit.
As with the userauth keys, there's a localised bodge when sending
algorithm names, where I just write a couple of extra entries into the
list when I notice that a key is RSA-typed. Then I arrange that the
selection of those entries sets the new variable s->hkflags to the
right value to pass to ssh_key_sign.
We parse enough of EXT_INFO to spot when the server advertises support
for them, and if it does, we upgrade the key algorithm name from
"ssh-rsa" to one of the other two, and set appropriate signing flags.
This doesn't actually end up using the ssh_rsa_sha256 / ssh_rsa_sha512
vtables I set up two commits ago, because it's easier to just vary the
flags word we pass to ssh_key_sign.
The upgrade is done by ad-hoc special-case code in ssh2userauth.c. I
could have done it by introducing a new ssh_keyalg vtable method for
'please upgrade to your favourite version of yourself according to
some set of flags from the BPP', but it just didn't seem like a good
idea at this stage, because it presupposes that quirks in the
algorithm selection are going to follow a consistent pattern, and I
think it's much more likely that the next weird thing in this area
will be something totally different. So I've left it as a localised
bodge for now, and we can always refactor it into something nicer once
we have more information and know what the nicer thing _is_.
We now add the appropriate advertisement to our KEXINIT that indicates
a willingness to receive EXT_INFO. Code in the BPP enforces that it
must appear in one of the permitted locations in the protocol (in
particular, this ensures a pre-key-exchange MITM can't get away with
inserting it into the initial cleartext segment of the protocol). And
when we receive it, we look through it for extension names we know
about.
No functional change (except for the advertisement in KEXINIT): we
don't yet actually do anything in response to any extension reported
in EXT_INFO.
This is the cleanest part of the RFC 8332 support: I simply add two
more RSA-based SSH-2 key algorithm vtables, both almost identical to
the existing one, with different ssh_id strings and signature flags.
Adding those to the HOSTKEY_ALGORITHMS list macro is enough to ensure
that we advertise support for the new identifiers in our client
KEXINIT, select the appropriate algorithm if the server announces one
or both of them too, and use the right version of the signature
validation.
Its boolean parameters were typed 'int', a hangover from before the
int-to-bool migration last year. It's not used in the current state of
the code base, so nobody noticed until now.
Uppity's built-in SFTP server makes up its file handle identifiers
using random_read(). But when that server is reused in psusan, which
doesn't have the random number generator enabled, you get an assertion
failure.
Introduced by commit 5891142aee, in which I invented
strbuf_shrink_to() and went round replacing lots of assignments of the
form 'sb->len = smaller_value' with calls to it. The bug is also in
0.74, because 34a0460f05 is a cherry-pick of the commit that
introduced it.
The difference between that assignment and strbuf_shrink_to is partly
that the latter checks by assertion that the new length really is
_smaller_ - it doesn't let you accidentally grow a strbuf's length
field beyond the limit of its buffer (or indeed at all). But also,
strbuf_shrink_to re-establishes the strbuf invariant that the text
logically in the buffer is always followed by a zero byte, so that
it's a valid C string.
Unfortunately, in one of the places I made this change, I was storing
binary data in the strbuf (so the terminating NUL is unimportant), and
immediately after decreasing the strbuf's length, I was doing a memcmp
one of whose arguments was the data I'd just chopped off the end of
the strbuf. So it _mattered_ that no random NUL had been splurged over
it.
Specifically, this happened in the run-length encoder used to compress
scrollback data, and had the effect that two components of the
compressed scrollback could be spuriously considered equal, if one of
them started with a legitimate zero byte and the other had a zero byte
written over it by this bug. Thanks to Michael Weller for a nice test
case that demonstrated a compressed scrollback line being decompressed
again as the wrong thing:
"NORMAL TEXT, \033[42mGREEN BACKGROUND\033[0m, NORMAL TEXT AGAIN"
If the above line is printed to the terminal (after being decoded as
if it was a C string literal), then only the words "GREEN BACKGROUND"
get a green background. But after that line is scrolled off the top of
the window, if you find it in the scrollback, then the rest of the
line to the right has also become green-backgrounded due to this bug.
This is a piece of conditioned-out code that I haven't used since I
originally invented the compressed scrollback format, which
decompressed every scrollback line immediately after compressing it to
check that the round-trip conversion worked. Now I have occasion to
actually use it, I find that (of course) changes around it have made
it not quite work any more: the thing the diagnostic code is passing
to decompressline hasn't had its length field filled in yet, because
that gets done 20 lines later.
Now you can compile with -DTERM_CC_DIAGS again, and it doesn't crash
_unless_ it detects the actual bug it was intended to spot.
We use this for detecting the Arm crypto extension and using it to
enable accelerated AES and/or SHA-{1,2}. Previously, I had code that
called glibc's getauxval(3) function, conditioned on #ifdef __linux__.
Now, instead, I do an autoconf test to query the presence of getauxval
itself (so that any other system with the same API can still work),
and alongside it, also check for the analogous FreeBSD libc function
elf_aux_info(3). As a result, building on Arm FreeBSD now gets the
accelerated-crypto autodetection.
I carefully set a 'finished' flag in the main source file on receipt
of the server_instance_terminated() callback, and then I plain forgot
to hook it up to the uxcliloop callback that says whether the program
should carry on running each time round the main loop. Now we actually
check the finished flag, and terminate the program if it's set.
We keep an internal 128-bit counter that's used as part of the hash
preimages. There's no real need to import all the mp_int machinery in
order to implement that: we can do it by hand using a small fixed-size
array and a trivial use of BignumADC. This is another inter-module
dependency that's easy to remove and useful to spinoff programs.
This changes the hash preimage calculation in the PRNG, because we're
now formatting our 128-bit integer in the fixed-length representation
of 16 little-endian bytes instead of as an SSH-2 mpint. This is
harmless (perhaps even mildly beneficial, due to the length now not
depending on how long the PRNG has been running), but means I have to
update the PRNG tests as well.
For use in spinoff programs: this is an alternative to proxy.c, which
provides the same API (to avoid link failures in modules like
x11fwd.c) but implements it in the trivial way, supporting no proxying
at all and just wrapping the underlying sk_new() and friends.
Rather like some of the tricks I did in mpint.h, this replaces the
unparametrised function random_setup_special() with one called
random_setup_custom() taking a hash-algorithm parameter.
The old syntax random_setup_special() still exists, and is a macro
wrapper on random_setup_custom() that passes ssh_sha512 as an
argument. This means I can keep the choice of hash function consistent
between the key generation front ends.
This adds potential flexibility: now, anyone wanting a different kind
of special RNG can make it out of whatever primitive they like. But a
more immediate point is to remove an inter-module dependency:
sshrand.c now doesn't need to be linked against the SHA-512 code.
This is mostly easy: it's just like drawing an underline, except that
you put it at a different height in the character cell. The only
question is _where_ in the character cell.
Pango, and Windows GetOutlineTextMetrics, will tell you exactly where
the font wants to have it. Following xterm, I fall back to 3/8 of the
font's ascent (above the baseline) if either of those is unavailable.
This is a small wrapper on 'sshfs' which allows it to use Plink as its
transport. Mostly useful for when I've already got a PuTTY session
open to a given host with connection sharing enabled, and want to
tunnel over that rather than painstakingly re-establishing a separate
connection.
Two minor memory-leak fixes on 0.74 seem not to be needed on master:
the fix in an early exit path of pageant_add_keyfile is done already
on master in a different way, and the missing sfree(fdlist) in
uxsftp.c is in code that's been completely rewritten in the uxcliloop
refactoring.
Other minor conflicts: the rework in commit b52641644905 of
ssh1login.c collided with the change from FLAG_VERBOSE to
seat_verbose(), and master and 0.74 each added an unrelated extra
field to the end of struct SshServerConfig.
This is a no-op merge, via 'git merge -s ours', which records that all
the commits up to this point on the 0.74 branch are bug fixes
cherry-picked from master, and don't need merging back to master.
From this point onwards, the 0.74 branch will contain fresh work that
_will_ need merging back to master. This preliminary non-merge allows
me to avoid needless conflicts during that process.
We received a report that if you enable Windows 10's high-contrast
mode, the text in PuTTY's installer UI becomes invisible, because it's
displayed in the system default foreground colour against a background
of the white right-hand side of our 'msidialog.bmp' image. That's fine
when the system default fg is black, but high-contrast mode flips it
to white, and now you have white on white text, oops.
Some research in the WiX bug tracker suggests that in Windows 10 you
don't actually have to use BMP files for your installer images any
more: you can use PNG, and PNGs can be transparent. However, someone
else reported that that only works in up-to-date versions of Windows.
And in fact there's no need to go that far. A more elegant answer is
to simply not cover the whole dialog box with our background image in
the first place. I've reduced the size of the background image so that
it _only_ contains the pretty picture on the left-hand side, and omits
the big white rectangle that used to sit under the text. So now the
RHS of the dialog is not covered by any image at all, which has the
same effect as it being covered with a transparent image, except that
it doesn't require transparency support from msiexec. Either way, the
background for the text ends up being the system's default dialog-box
background, in the absence of any images or controls placed on top of
it - so when the high-contrast mode is enabled, it flips to black at
the same time as the text flips to white, and everything works as it
should.
The slight snag is that the pre-cooked WiX UI dialog specifications
let you override the background image itself, but not the Width and
Height fields in the control specifications that refer to them. So if
you just try to drop in a narrow image in the most obvious way, it
gets stretched across the whole window.
But that's not a show-stopper, because we're not 100% dependent on
getting WiX to produce exactly the right output. We already have the
technology to postprocess the MSI _after_ it comes out of WiX: we're
using it to fiddle the target-platform field for the Windows on Arm
installers. So all I had to do was to turn msiplatform.py into a more
general msifixup.py, add a second option to change the width of the
dialog background image, and run it on the x86 installers as well as
the Arm ones.