1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00
Commit Graph

5528 Commits

Author SHA1 Message Date
Simon Tatham
e0a76971cc New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of

   if (logical_array_len >= physical_array_size) {
       physical_array_size = logical_array_len * 5 / 4 + 256;
       array = sresize(array, physical_array_size, ElementType);
   }

which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.

The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).

Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.

This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:15:38 +00:00
Simon Tatham
5e9213ca48 Move the Minefield function prototypes into puttymem.h.
I haven't tried compiling with /DMINEFIELD in a while, and when I just
did, I found that the declarations in winstuff.h weren't actually
being included by memory.c where they're needed.
2019-02-28 20:02:39 +00:00
Simon Tatham
a432943d19 Remove reallocation loop in Windows get_hostname.
I've just noticed that the MSDN docs for WinSock gethostname()
guarantee that a size-256 buffer is large enough. That seems a lot
simpler than the previous faff.
2019-02-28 20:02:39 +00:00
Simon Tatham
59c8df4130 Remove duplicate coroutine macros.
pageant.c and sshshare.c each had an extra copy of crBegin and
crFinishV, dating from when the main versions were kept in ssh.c where
they couldn't be conveniently #included by other modules. Now they're
in sshcr.h, where they can be, so there's no need to have extra copies
of them anywhere.

(But I've left the crGetChar macro in each of those files, because
those really are specific to the particular context, referring to an
extra variable that clients of the more general sshcr.h macros won't
all have.)
2019-02-28 18:05:38 +00:00
Simon Tatham
4ecc3f3c09 Fix a couple of syntactically dangerous macros.
The live versions of the dmemdump macros had a trailing semicolon in
the expansion, which would cause them to break if used in the wrong
syntactic context (e.g. between if and else with the natural semicolon
at the call site). The conditioned-out versions of those and of
debug() itself expanded to the empty string in place of the more usual
((void)0). And SECOND_PASS_ONLY in gtkmain.c's command-line handling
should have had the standard do ... while(0) wrapper to make it
reliably a single statement.
2019-02-28 18:00:31 +00:00
Simon Tatham
3e881a4248 Fix a few memory leaks.
Mostly noticed in passing while using Address / Leak Sanitiser to
check over the previous commit. One highlight here is freeing of the
previous iqmp value in rsa_verify, which was actually a potentially
sensitive leak, introduced in the mp_int rewrite (commit 25b034ee3).
2019-02-28 06:44:00 +00:00
Simon Tatham
d07d7d66f6 Replace more ad-hoc growing char buffers with strbuf.
I've fixed a handful of these where I found them in passing, but when
I went systematically looking, there were a lot more that I hadn't
found!

A particular highlight of this collection is the code that formats
Windows clipboard data in RTF, which was absolutely crying out for
strbuf_catf, and now it's got it.
2019-02-28 06:42:37 +00:00
Simon Tatham
e3e4315033 Don't ask again about weak crypto primitives on rekey.
If the user clicks 'ok' to a prompt such as 'should we carry on even
though the server only supports diffie-hellman-stage-whisper-sha0',
then we've done our duty to warn them about weak crypto, and shouldn't
nag them with the same confirmation prompt again and again in
subsequent rekeys. So now we keep a tree234 of all the algorithms the
user has consented to, so as to ask about each one at most once.
2019-02-27 21:10:00 +00:00
Simon Tatham
d147f764ea Plink: fix mishandling of launchable Default Settings.
Plink's hostname argument can refer to a saved session instead of a
hostname. We test this by trying to load it as a session, and seeing
if the resulting Conf is launchable. But if Default Settings itself is
launchable (e.g. if it has the protocol set to Serial) then that can
happen even if there is no saved session with that name - in which
case we'll _never_ fall back to treating the argument as a host name.

Fixed by also checking the new success flag returned from do_defaults.
2019-02-27 20:31:48 +00:00
Simon Tatham
55123b105d load_settings, do_defaults: return a boolean success flag.
Now the caller of one of those functions can tell whether the session
it loaded actually existed at all, or whether it was made up by
settings.c.
2019-02-27 20:30:47 +00:00
Simon Tatham
69b216c116 Windows open_settings_r: return NULL for a nonexistent session.
Previously, we returned a valid settings_r containing a null HKEY.
That didn't actually cause trouble (I think all the registry API
functions must have spotted the null HKEY and returned a clean error
code instead of crashing), but it means the caller can't tell if the
session really existed or not. Now we return NULL in that situation,
and close_settings_r avoids crashing if we pass the NULL to it later.
2019-02-27 20:29:13 +00:00
Simon Tatham
1db5001260 Replace a couple more #defines with inline functions.
My trawl of all the vtable systems in the code spotted a couple of
other function-like macros in passing, which might as well be
rewritten as inline functions too for the same reasons.
2019-02-27 19:48:16 +00:00
Simon Tatham
1b4a08a953 Replace method-dispatch #defines with inline functions.
This replaces all the macros like ssh_key_sign() and win_draw_text()
which take an object containing a vtable pointer and do the
dereferencing to find the actual concrete method to call. Now they're
all inline functions, which means more sensible type-checking and more
comprehensible error reports when the types go wrong, and also means
that there's no risk of double-evaluating the object argument.
2019-02-27 19:48:14 +00:00
Simon Tatham
07ebd88c3a Fix selection and cursor handling for bidi + wide chars.
Commit fec93d5e0 missed a piece: when we hand wcTo to
term_bidi_cache_store and it uses it to set up the mapping between
physical and logical character positions for cursor and selection
handling, it will assume wcTo has as many entries as there are columns
in the terminal. But in fact now wcTo may be shorter than that, so
term_bidi_cache_store also needs to pay attention to the nchars field.
2019-02-26 18:42:54 +00:00
Simon Tatham
801ab68eac Rewrite invent_firstbits().
Instead of repeatedly looping on the random number generator until it
comes up with two values that have a large enough product, the new
version guarantees only one use of random numbers, by first counting
up all the possible pairs of values that would work, and then
inventing a single random number that's used as an index into that
list.

I've done the selection from the list using constant-time techniques,
not particularly because I think key generation can be made CT in
general, but out of sheer habit after the last few months, and who
knows, it _might_ be useful.

While I'm at it, I've also added an option to make sure the two
firstbits values differ by at least a given value. For RSA, I set that
value to 2, guaranteeing that even if the smaller prime has a very
long string of 1 bits after the firstbits value and the larger has a
long string of 0, they'll still have a relative difference of at least
2^{-12}. Not that there was any serious chance of the primes having
randomly ended up so close together as to make the key in danger of
factoring, but it seems like a silly thing to leave out if I'm
rewriting the function anyway.
2019-02-26 07:12:57 +00:00
Simon Tatham
1a7521a0a7 New mpint function mp_get_integer().
If you have an mp_int that you know will fit in an ordinary integer
type, this function gives it to you in that form.
2019-02-26 07:12:57 +00:00
Simon Tatham
35f071f61c Minor refactoring in terminal.c.
The actual calls to win_draw_{text,cursor} in do_paint() were
duplicated in two places, and I may want to change them soon, so it's
convenient to centralise them.
2019-02-26 07:12:57 +00:00
Simon Tatham
fec93d5e05 Make bidi work with wide characters.
Previously, any double-width character would break the bidi algorithm,
because of the quirk of data representation in which we store UCSWIDE
(0xDFFF) in the right-hand termchar overlapped by the character.
UCSWIDE has bidirectional character class L according to minibidi's
getType(), so it disrupted the algorithm.

Now we remove UCSWIDE from the input line before passing it to
do_bidi(), replacing it with an 'nchars' field in the bidi_char
structure indicating single or double width, and put the UCSWIDEs back
afterwards once do_bidi returns.
2019-02-25 20:51:17 +00:00
Simon Tatham
8edfc767a3 minibidi.c: include putty.h and fix clashes.
The bidi_char structure was declared twice, with nothing to keep them
in sync; also, is_rtl had a mismatch of return types.
2019-02-25 20:30:38 +00:00
Jacob Nevins
ca90a36bcd Man page documentation of sanitise options.
These were added in commits 91cf47dd0d and 2675f9578d.
2019-02-21 01:00:44 +00:00
Jacob Nevins
21299b9cd5 Remove duplicate -no-sanitise-stderr from usage(). 2019-02-21 00:27:56 +00:00
Simon Tatham
2675f9578d File transfer tools: sanitise remote filenames and stderr.
This commit adds sanitisation to PSCP and PSFTP in the same style as
I've just put it into Plink. This time, standard error is sanitised
without reference to whether it's redirected (at least unless you give
an override option), on the basis that where Plink is _sometimes_ an
SSH transport for some other protocol, PSCP and PSFTP _always_ are.

But also, the sanitiser is run over any remote filename sent by the
server, substituting ? for any control characters it finds. That
removes another avenue for the server to deliberately confuse the
display.

This commit fixes our bug 'pscp-unsanitised-server-output', aka the
two notional 'vulnerabilities' CVE-2019-6109 and CVE-2019-6110.
(Although we regard those in isolation as only bugs, not serious
vulnerabilities, because their main threat was in hiding the evidence
of a server having exploited other more serious vulns that we never
had.)
2019-02-20 07:27:22 +00:00
Simon Tatham
91cf47dd0d Plink: default to sanitising non-tty console output.
If Plink's standard output and/or standard error points at a Windows
console or a Unix tty device, and if Plink was not configured to
request a remote pty (and hence to send a terminal-type string), then
we apply the new control-character stripping facility.

The idea is to be a mild defence against malicious remote processes
sending confusing escape sequences through the standard error channel
when Plink is being used as a transport for something like git: it's
OK to have actual sensible error messages come back from the server,
but when you run a git command, you didn't really intend to give the
remote server the implicit licence to write _all over_ your local
terminal display. At the same time, in that scenario, the standard
_output_ of Plink is left completely alone, on the grounds that git
will be expecting it to be 8-bit clean. (And Plink can tell that
because it's redirected away from the console.)

For interactive login sessions using Plink, this behaviour is
disabled, on the grounds that once you've sent a terminal-type string
it's assumed that you were _expecting_ the server to use it to know
what escape sequences to send to you.

So it should be transparent for all the use cases I've so far thought
of. But in case it's not, there's a family of new command-line options
like -no-sanitise-stdout and -sanitise-stderr that you can use to
forcibly override the autodetection of whether to do it.

This all applies the same way to both Unix and Windows Plink.
2019-02-20 07:27:22 +00:00
Simon Tatham
462b8c7b84 Give FORCE_ON / FORCE_OFF / AUTO an enum name.
That will let me declare variables of that type: it's 'enum TriState'.
2019-02-20 07:27:22 +00:00
Simon Tatham
6593009b0e New utility object, StripCtrlChars.
This is for sanitising output that's going to be sent to a terminal,
if you don't want it to be able to send arbitrary escape sequences and
thereby (for example) move the cursor back up to existing text on the
screen and overprint it confusingly.

It works using the standard C library: we convert to a wide-character
string and back, and then use wctype.h to spot control characters in
the intermediate form. This means its idea of the conversion character
set is locale-based rather than any of our own charset library's fixed
settings - which is what you want if the aim is to protect your local
terminal (which we assume the system locale represents accurately).

This also means that the sanitiser strips things that will _act_ as
control characters when sent to the local terminal, whether or not
they were intended as control characters by a server that might have
had a different character set in mind. Since the main aim is to
protect the local terminal rather than to faithfully replicate the
server's intention, I think that's the right criterion.

It only strips control characters at the charset-independent layer,
like backspace, carriage return and the escape character: wctype.h
classifies those as control characters, but classifies as printing all
of the more Unicode-specific controls like bidirectional overrides.
But that's enough to prevent cursor repositioning, for example.

stripctrl.c comes with a test main() of its own, which I wasn't able
to fold into testcrypt and put in the test suite because of its
dependence on the system locale - it wouldn't be guaranteed to work
the same way on different test systems anyway.

A knock-on build tweak: because you can feed data into this sanitiser
in chunks of arbitrary size, including partial multibyte chars, I had
to use mbrtowc() for the decoding, and that means that in the 'old'
Win32 builds I have to link against the Visual Studio C++ library as
well as the C library, because for some reason that's where mbrtowc
lived in VS2003.
2019-02-20 07:27:22 +00:00
Simon Tatham
f9b1a2bbc2 New Windows utility function: is_console_handle().
Rather like isatty() on Unix, this tells you if a raw Windows HANDLE
points at a console or not. Useful to know if your standard output or
standard error is going to be shown to a user, or redirected to
something that will make automated use of it.
2019-02-20 07:27:13 +00:00
Simon Tatham
bc1aa9c656 Add BinarySink wrappers on existing forms of output.
There's now a stdio_sink, whose write function calls fwrite on the
given FILE *; a bufchain_sink, whose write function appends to the
given bufchain; and on Windows there's a handle_sink whose write
function writes to the given 'struct handle'. (That is, not the raw
Windows HANDLE, but our event-loop-friendly wrapper on it.)

Not yet used for anything, but they're about to be.
2019-02-20 07:27:13 +00:00
Simon Tatham
5dadbdf556 ssh_sftp_do_select: don't fail if a callback is pending.
ssh_sftp_loop_iteration() used to return failure if no file handle was
in use for the select loop, on the basis that that means select would
just loop forever. But if there's a toplevel callback pending - in
particular, if it's going to do something like emptying ssh->in_raw
which will put an fd _back into_ the next iteration of the select loop
- then that's not a good enough reason to return permanent failure.
Just go round the loop, run the callback, and try again.
2019-02-17 20:30:14 +00:00
Simon Tatham
5bc6db4b96 Call ssh_check_frozen when BPP consumes input.
In commit 0f405ae8a, I arranged to stop reading from the SSH
connection if the in_raw bufchain got too big. But in at least some
tools (this bit me just now with PSCP), nothing actually calls
ssh_check_frozen again when the bufchain clears, so it stays frozen.

Now ssh_check_frozen is non-static, and all the BPP implementations
call it whenever they consume data from ssh->in_raw.
2019-02-17 20:30:14 +00:00
Simon Tatham
85550641d7 uxpty.c: initialise pty->pending_eof.
valgrind just pointed out that it wasn't.
2019-02-13 19:36:31 +00:00
Simon Tatham
75dda5e86f Fix crash on entering wrong passphrase.
When I added the new call to ssh_key_invalid the other day, I forgot
to avoid calling it if the key is NULL (and therefore even more
obviously invalid).
2019-02-11 20:20:50 +00:00
Simon Tatham
8957e613bc Add missing sanity checks in ssh_dss_verify.
The standard says we should be checking that both r,s are in the range
[1,q-1]. Previously we were effectively reducing s mod q in the course
of inversion, and modinv() was guaranteeing never to return zero; the
remaining missing checks were benign. But the change from Bignum to
mp_int altered the error behaviour, and combined with the missing
upper bound check on s, made it possible to continue verification with
w == 0 mod q, which is a bad case.

Added a small DSA test case, including a check that none of these
types of signatures validates.
2019-02-10 20:10:41 +00:00
Simon Tatham
22131a51fa Windows PuTTYgen: bound entropy input by PRNG state size.
Although I've reinstated the tedious manual mouse input, I can at
least reduce the amount of it that the user is required to provide:
the new PRNG has a hard limit on the size of its seed, so once we've
generated enough entropy to fill that up, there's no point in
collecting more, even if we're generating a particularly large key.
2019-02-10 13:44:50 +00:00
Simon Tatham
4d288dc3e9 Windows PuTTYgen: reinstate mouse-based entropy collection.
This reverts the policy change in 6142013ab (though not the detailed
code changes - I've kept the reorganised code layout). Now the old
mouse-based manual entropy collection is once again required when
generating a public key.

Rationale: I came across Wikipedia's page on CryptGenRandom which
mentioned that it was not a true kernel-level PRNG of the /dev/random
variety, but rather a thing running in userland, no different in
principle from PuTTY's own. So I think that makes it no longer a thing
we should rely on for all our entropy, and I'm relegating it back to
being just one entropy source among many.
2019-02-10 13:38:15 +00:00
Simon Tatham
9cb8c4bcb7 mp_cond_swap: add a brute-force 'volatile'.
With this change, my new side-channel test system gets a 100% pass
rate when compiled with clang -O3 on Ubuntu 18.10. Previously, it had
three failing tests (namely the three ECC multiply functions), all due
to inconsistent control flow inside mp_cond_swap.

I admit I don't really understand whether this is really necessary or
not, so I'm playing it safe. The problem _seems_ to be that clang has
generated one version of the cond_swap loop using integer arithmetic
and another using MMX vectors, so the obvious suspect is alignment -
probably mp_cond_swap is processing an iteration of the loop up front
until its pointer is 16-byte aligned and then switching over to the
vectorised version. But on the other hand, when I experimentally tried
forcing allocations to be 16- or even 32-byte aligned, it didn't make
a difference. And I don't speak x86 vector instructions very well (in
fact barely at all), so I'm not even completely sure of whether the
code I was reading did what I thought it did; so I'm more comfortable
with simply applying brute force to get some code generation that the
automated test is genuinely happy with.
2019-02-10 13:16:12 +00:00
Simon Tatham
83db341e8a New test system to detect side channels in crypto code.
All the work I've put in in the last few months to eliminate timing
and cache side channels from PuTTY's mp_int and cipher implementations
has been on a seat-of-the-pants basis: just thinking very hard about
what kinds of language construction I think would be safe to use, and
trying not to absentmindedly leave a conditional branch or a cast to
bool somewhere vital.

Now I've got a test suite! The basic idea is that you run the same
crypto primitive multiple times, with inputs differing only in ways
that are supposed to avoid being leaked by timing or leaving evidence
in the cache; then you instrument the code so that it logs all the
control flow, memory access and a couple of other relevant things in
each of those runs, and finally, compare the logs and expect them to
be identical.

The instrumentation is done using DynamoRIO, which I found to be well
suited to this kind of work: it lets you define custom modifications
of the code in a reasonably low-effort way, and it lets you work at
both the low level of examining single instructions _and_ the higher
level of the function call ABI (so you can give things like malloc
special treatment, not to mention intercepting communications from the
program being instrumented). Build instructions are all in the comment
at the top of testsc.c.

At present, I've found this test to give a 100% pass rate using gcc
-O0 and -O3 (Ubuntu 18.10). With clang, there are a couple of
failures, which I'll fix in the next commit.
2019-02-10 13:09:53 +00:00
Simon Tatham
fa4a7dd3d5 Stop falling back to 16-bit BignumInt on VS Arm builds.
The case previously conditioned on _M_IX86, where we use __int64 as
the BignumDblInt type, is actually valid on any Visual Studio target
platform at all, so it's safe to remove that condition and let it
apply to _M_ARM and _M_ARM64 as well. The only situation in which we
_shouldn't_ use that case for Visual Studio builds is when we have
something even better available, such as the x86-64 intrinsics for
add-with-carry and double-width multiply.
2019-02-10 09:05:47 +00:00
Simon Tatham
bc11f74c74 Stop aborting the connection if Pageant won't sign.
There's been a FIXME comment in there for ages saying we should do
something less drastic than ssh_sw_abort(). This actually came up in
the course of testing Pageant's support for the new RSA validity
check, so I've fixed it: if Pageant won't deliver us a signature from
the private key we'd like, then we treat it the same as any other auth
method failure: shrug and move on to the next method on our list (or
even just the next key in Pageant).
2019-02-10 09:05:47 +00:00
Simon Tatham
f133abe521 Give a sensible error when using a too-short RSA key.
The ssh_signkey vtable has grown a new method ssh_key_invalid(), which
checks whether the key is going to be usable for constructing a
signature at all. Currently the only way this can fail is if it's an
RSA key so short that there isn't room to put all the PKCS#1
formatting in the signature preimage integer, but the return value is
an arbitrary error message just in case more reasons are needed later.

This is tested separately rather than at key-creation time because of
the signature flags system: an RSA key of intermediate length could be
valid for SHA-1 signing but not for SHA-512. So really this method
should be called at the point where you've decided what sig flags you
want to use, and you're checking if _those flags_ are OK.

On the verification side, there's no need for a separate check. If
someone presents us with an RSA key so short that it's impossible to
encode a valid signature using it, then we simply regard all
signatures as invalid.
2019-02-10 09:05:47 +00:00
Simon Tatham
40843b432a dss_sign(): fix a theoretically possible overflow.
I computed hash + x*r by first computing x*r, and then using
mp_add_into to add the hash to it in the same bignum. But if the
result of x*r had been allocated an mp_int only just large enough to
contain it, then the addition of the hash might have made it overflow
and generated a bogus signature.

I've never seen that happen, and for all I know word sizes may make it
completely impossible. But it's a theoretical possibility, and easy to
fix now that I've happened to spot it in passing.
2019-02-10 09:05:47 +00:00
Simon Tatham
f659614272 ecc.[ch]: add elliptic-curve point_copy_into functions.
This will let my upcoming new test of memory access patterns run a
sequence of tests on different elliptic-curve data which is stored at
the same address each time.
2019-02-09 17:52:25 +00:00
Simon Tatham
30117bff55 Add primegen() to the testcrypt API.
I just found I wanted to generate a prime with particular properties,
and I knew PuTTY's prime generator could manage it, so it was easier
to add this function to testcrypt for occasional manual use than to
look for another prime-generator with the same feature set!

I've wrapped the function so as to remove the three progress-
reporting parameters.
2019-02-09 17:52:23 +00:00
Simon Tatham
03492ab593 minibidi: fix read past end of line in rule W5.
The check for a sequence of ET with an EN after it could potentially
skip ETs all the way up to the end of the buffer and then look for an
EN in the following nonexistent array element. Now it only skips ETs
up to count-1, in the same style as the similar check in rule N1.

Change-Id: Ifdbae494a22d1b96bf49ae1bcae0efb901565f45
2019-02-09 14:12:16 +00:00
Simon Tatham
e7341d8e97 testcrypt: fix typo in a key algorithm name.
I haven't actually written any tests for the NIST ECDSA algorithms
yet, or else I'd have noticed that one of them wasn't spelled right.
2019-02-09 14:11:13 +00:00
Simon Tatham
7b52943dde .gitignore update: add uxconfig.in~ .
I don't know why this sometimes gets created, but it's clearly the
kind of thing that belongs in .gitignore if it exists at all.
2019-02-09 14:10:30 +00:00
Simon Tatham
bfae3ee96e mpint: add a few simple bitwise operations.
I want to use mp_xor_into as part of an upcoming test program, and
while I'm at it, I thought I'd add a few other obvious bitops too.
2019-02-09 14:10:30 +00:00
Simon Tatham
8ccbd164c7 uxsftpserver: cast st.st_size to uintmax_t.
This fixes a build failure reported by Colin on platforms (armel,
mipsel) where off_t and PRIu64 don't match.
2019-02-07 20:06:55 +00:00
Simon Tatham
85eaaa86b7 Avoid undefined left shift in ANSI macro.
If term->esc_query == -1 (reflecting an escape sequence in which the
CSI is followed by a prefix character other than ?) then the ANSI
macro shouldn't shift it left by 8, because that's undefined behaviour
(although in practice I'd be very surprised if any compiler has
actually miscompiled it yet).

Multiplying it by 256 is a safe alternative which has the behaviour I
wanted.
2019-02-06 21:46:10 +00:00
Simon Tatham
5b17a2ce20 Assorted further migration to ptrlen.
The local put_mp_*_from_string functions in import.c now take ptrlen
(which simplifies essentially all their call sites); so does the local
function logwrite() in logging.c, and so does ssh2_fingerprint_blob.
2019-02-06 21:46:10 +00:00
Simon Tatham
751a989091 Add and use BinarySource_*INIT_PL.
A great many BinarySource_BARE_INIT calls are passing the two halves
of a ptrlen as separate arguments. It saves a lot of call-site faff to
have a variant of the init function that just takes the whole ptrlen
in one go.
2019-02-06 21:46:10 +00:00