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

7432 Commits

Author SHA1 Message Date
Simon Tatham
8bd75b85ed Some support for wide-character filenames in Windows.
The Windows version of the Filename structure now contains three
versions of the pathname, in UTF-16, UTF-8 and the system code page.
Callers can use whichever is most convenient.

All uses of filenames for actually opening files now use the UTF-16
version, which means they can tolerate 'exotic' filenames, by which I
mean those including Unicode characters outside the host system's
CP_ACP default code page.

Other uses of Filename structures inside the 'windows' subdirectory do
something appropriate, e.g. when printing a filename inside a message
box or a console message, we use the UTF-8 version of the filename
with the UTF-8 version of the appropriate API.

There are three remaining pieces to full Unicode filename support:

One is that the cross-platform code has many calls to
filename_to_str(), embodying the assumption that a file name can be
reliably converted into the unspecified current character set; those
will all need changing in some way.

Another is that write_setting_filename(), in windows/storage.c, still
saves filenames to the Registry as an ordinary REG_SZ in the system
code page. So even if an exotic filename were stored in a Conf, that
Conf couldn't round-trip via the Registry and back without corrupting
that filename by coercing it back to a string that fits in CP_ACP and
therefore doesn't represent the same file. This can't be fixed without
a compatibility break in the storage format, and I don't want to make
a minimal change in that area: if we're going to break compatibility,
then we should break it good and hard (the Nanny Ogg principle), and
devise a completely fresh storage representation that fixes as many
other legacy problems as possible at the same time. So that's my plan,
not yet started.

The final point, much more obviously, is that we're still short of
methods to _construct_ any Filename structures using a Unicode input
string! It should now work to enter one in the GUI configurer (either
by manual text input or via the file selector), but it won't
round-trip through a save and load (as discussed above), and there's
still no way to specify one on the command line (the groundwork is
laid by commit 10e1ac7752 but not yet linked up).

But this is a start.
2023-05-29 15:41:50 +01:00
Simon Tatham
85680c77c0 Make x11_get_auth_from_authfile take a Filename.
I think the only reason it currently takes a plain string is because
its interesting caller (in unix/x11.c) has just constructed a string
out of an environment variable, and it seemed like the path of least
effort not to bother wrapping it into a proper Filename. But when
Filename on Windows becomes more interesting, we'll need it to take
the full version.
2023-05-29 15:41:50 +01:00
Simon Tatham
1adcb200f7 dialog.c: give ctrl->fileselect.filter an opaque type.
The values of that field in a Control structure are already
platform-dependent: you're only supposed to set them in cross-platform
code by using #defined names that each platform will define
differently.

Now I need the _type_ as well as the values to be opaque, because I'm
about to make a change on Windows that turns it into a wide character
string instead of a char string.
2023-05-29 15:41:50 +01:00
Simon Tatham
e1c6f61985 New Windows utility function: request_file_w.
Just like the existing request_file, but wide-character oriented.
2023-05-29 15:31:45 +01:00
Simon Tatham
059f42aa56 New Windows utility function: GetDlgItemTextW_alloc.
Just like the existing GetDlgItemText_alloc, but for wide strings.
2023-05-29 15:31:43 +01:00
Simon Tatham
392be3e494 New utility function: decode_utf8_to_wide_string.
We already had encode_wide_string_as_utf8, which treats the wide
string as UTF-16 or UTF-32 as appropriate to the size of wchar_t. I'm
about to need the inverse function, and was surprised that it didn't
already exist (even though enough component parts did to make it easy).
2023-05-29 15:08:49 +01:00
Simon Tatham
36db93748e New utility function: dupwcs.
Just like dupstr, but for wchar_t strings.
2023-05-29 15:08:49 +01:00
Simon Tatham
5f43d11f83 Add UTF-8 flag to the Windows message_box() wrapper.
message_box() previously differed from the real MessageBox API
function in that it permitted the user to provide a help context to be
used for a Help button in the dialog box.

Now it adds a second unusual ability: you can specify that the text
and caption strings are in UTF-8 rather than the system code page.
2023-05-29 15:08:48 +01:00
Simon Tatham
d22ccbac6f Fix UTF-8 flag checks in the Windows conio system.
Having constructed a conio object with its own 'utf8' flag, we should
be checking that flag at time of use rather than the global
conio_use_utf8 (which was already taken into account at setup time).
Otherwise we miss the whole point, which is that without the override
flag turning off UTF-8, _some_ uses of the system should use the
default code page and not UTF-8.
2023-05-28 13:29:54 +01:00
Simon Tatham
8cf372d4a2 NTRU: remove a pointless failure check.
In the key generation step where we invert 3f in the field
Z_q/<x^p-x-1>, I was carefully checking for failure, on the grounds
that even a field does have _one_ non-invertible element, namely zero.
But I forgot that we'd generated f in such a way that it can't
possibly be zero. So that failure check is pointless.

(However, I've retained it in the form of an assertion.)
2023-05-28 09:59:41 +01:00
Simon Tatham
6aca7f1eef windows/window.c: move more variables into WinGuiSeat.
In commit f9e572595b I claimed that I'd removed very nearly all
the global and static variables from windows/window.c. It turns out
that this was wildly overoptimistic - I missed quite a few of them!
I'm not quite sure how I managed that; my best guess is that I used an
underpowered 'nm' command that failed to find some classes of
variable.

Some of the remaining function-scope statics were removed completely
by commit afb3dab1e9 just now. In this commit, I've swept up some
more and turn them into fields of WinGuiSeat, where they should have
been moved last September.

The (hopefully complete this time) list of remaining variables,
generated by running this rune in the Windows build directory:

  nm windows/CMakeFiles/putty.dir/window.c.obj |
     grep -E '^([^ ]+)? *[bBcCdDgGsS] [^\.]'

consists of the following variables which are legitimately global
across the whole process and not related to a particular window:

 - 'hinst' and 'hprev', instance handles for Windows loadable modules

 - 'classname' in the terminal_window_class_a() and
   terminal_window_class_w() functions, which allocate a window class
   reusably

 - some pointers to Windows API functions retrieved via the
   DECL_WINDOWS_FUNCTION / GET_WINDOWS_FUNCTION system, such as
   p_AdjustWindowRectExForDpi and p_FlashWindowEx

 - some pointers to Windows API functions set up by assigning them at
   startup to the right one of the ANSI or Unicode version depending on
   the Windows version, e.g. sw_DefWindowProc and sw_DispatchMessage

 - 'unicode_window', a boolean flag set at the same time as those
   sw_Foo function pointers

 - 'sesslist', storing the last-retrieved version of the saved
   sessions menu

 - 'cursor_visible' in show_mouseptr() and 'forced_visible' in
   update_mouse_pointer(), each of which tracks the cumulative number
   of times that function has shown or hidden the mouse pointer, so as
   to manage its effect on the global state updated by ShowCursor

 - 'trust_icon', loaded from the executable's resources

 - 'wgslisthead', the list of all active WinGuiSeats

 - 'wm_mousewheel', the window-message id we use for mouse wheel
   events

and the following which are nothing to do with our code:

 - '_OptionsStorage' in __local_stdio_printf_options() and
   __local_stdio_scanf_options(), which I'd never noticed before, but
   apparently are internal to a standard library header.
2023-05-27 17:45:15 +01:00
Simon Tatham
322984d635 do_text_internal: fix bug in the lpDx_maybe mechanism.
lpDx_maybe was a pointer defined to point at either lpDx itself or
NULL, depending on whether the code decided it needed to pass the lpDx
array of per-character pixel offsets to various functions during
drawing (based in turn on whether the font was variable-pitch).

lpDx is reallocated as necessary, which means lpDx_maybe must be kept
up to date. This was achieved by resetting it to lpDx if it was
already non-NULL.

But lpDx starts out as NULL before the first reallocation, so that
this can't work - it'll be initialised to NULL even if we _did_ want
to use it, and then at the first realloc, it won't be updated!

Before the previous commit turned lpDx from a static into an automatic
variable, this would have been a rare bug affecting only the first
call to the function. Now it will happen all the time, which is
better, because we can notice and fix it.

Replaced lpDx_maybe completely with a boolean flag indicating whether
we should pass lpDx to drawing functions.
2023-05-27 17:43:02 +01:00
Simon Tatham
afb3dab1e9 Remove some pointless 'static' qualifiers.
In windows/window.c, a few variables inside functions were declared as
static, with no particular purpose that I can see: they don't seem to
have any reason to persist between calls to the function. So it makes
more sense to have them be ordinary stack-allocated automatic
variables.

Static variables removed by this commit:

 - 'RECT ss' in reset_window.
 - 'WORD keys[3]' and 'BYTE keysb[3]' in TranslateKey.
 - several (buffer, length) pairs in do_text_internal.
 - keys_unicode[] in TranslateKey.

All of these variables were originally introduced in patches credited
to Robert de Bath, which means I can't even try to reconstruct my
original thought processes, because they weren't _my_ thoughts anyway.
The arrays in do_text_internal are the easiest to understand: they're
reallocated larger as necessary, and making them static means the
allocation from a previous call can be reused, saving a malloc (though
I don't think that's a good enough reason to bother, these days).

The fixed-size static arrays and RECT are harder to explain. I suspect
they might originally have been that way because of 1990s attitudes to
performance: in x86-32 it's probably marginally faster to give your
variables constant addresses than sp-relative ones, and in the 1990s
computers were much slower, so there's an argument for making things
static if you have no _need_ to make them automatic. These days, the
difference is negligible, and persistent state is much more widely
recognised as a risk!

But keys_unicode[] is by far the strangest, because there was code
that clearly _did_ expect it to persist between calls, namely three
assignments to keys_unicode[0] near the end of the function after it's
finished being used for any other purpose, and a conditioned-out set
of debug() calls at the top of the function that print its contents
before anything has yet written to it.

But as far as I can see, the persistent data in the array is otherwise
completely unused. In any call to the function, if keys_unicode is
used at all, then it's either written directly by a call to ToAsciiEx,
or else (for pre-NT platforms) converted from ToAsciiEx's output via
MultiByteToWideChar. In both cases, the integer variable 'r' indicates
how many array elements were written, and subsequent accesses only
ever read those elements. So the assignments to keys_unicode[0] at the
end of the previous call will be overwritten before anything at all
can depend on them - with the exception of those debug statements.

I don't really understand what was going on here. It's tempting to
guess that those final assignments must have once done something
useful, and the code that used them was later removed. But the source
control history doesn't bear that out: a static array of three
elements (under its original name 'keys') was introduced in commit
0d5d39064a, and then commits 953b7775b3 and 26f1085038
added the other two assignments. And as far as I can see, even as of
the original commit 0d5d39064a, the code already had the property
that there was a final assignment to keys[0] which would inevitably be
overwritten in the next call before it could affect anything.

So I'm totally confused about what those assignments were _ever_
useful for. But an email thread from the time suggests that some of
those patches were being rebased repeatedly past other work (or
rather, the much less reliable CVS analogue of rebasing), so my best
guess is that that's where the confusion crept in - perhaps in RDB's
original version of the code they did do something useful.

Regardless of that, I'm pretty convinced that persistent array can't
be doing anything useful _now_. So I'm taking it out. But if anyone
reports a bug resulting from this change, then I'll eat my words - and
with any luck the details of the bug report will give us a clue what's
going on, and then we can put back some equivalent functionality with
much better comments!
2023-05-27 17:43:02 +01:00
Jacob Nevins
14d47544ad Merge bug-compatibility-mode rename from 'pre-0.79'. 2023-05-05 23:21:38 +01:00
Jacob Nevins
56b16bdc76 Rename the just-added bug-compatibility mode.
The configuration dialog control for the SSH bug-compatibility mode
added in d663356634 didn't quite fit on Windows.
2023-05-05 23:20:58 +01:00
Simon Tatham
356ccf489b Merge SSH fixes from 'pre-0.79'. 2023-05-05 00:06:00 +01:00
Simon Tatham
d663356634 Work around key algorithm naming change in OpenSSH <= 7.7.
When you send a "publickey" USERAUTH_REQUEST containing a certified
RSA key, and you want to use a SHA-2 based RSA algorithm, modern
OpenSSH expects you to send the algorithm string as
rsa-sha2-NNN-cert-v01@openssh.com. But 7.7 and earlier didn't
recognise those names, and expected the algorithm string in the
userauth request packet to be ssh-rsa-cert-v01@... and would then
follow it with an rsa-sha2-NNN signature.

OpenSSH itself has a bug workaround for its own older versions. Follow
suit.
2023-05-05 00:05:28 +01:00
Simon Tatham
cfe6fd95a7 userauth: fix replacement of embedded with detached RSA cert.
If you specify a detached certificate, it's supposed to completely
replace any certificate that might have been embedded in the input PPK
file. But one thing wasn't working: if the key was RSA, and the server
was using new SHA-2 based RSA, and the user provided both an embedded
_and_ detached certificate, then the initial call to
ssh2_userauth_signflags would upgrade the ssh-rsa-cert-... key type to
rsa-sha2-NNN-cert-..., which ssh2_userauth_add_alg_and_publickey's
call to ssh_keyalg_related_alg would not recognise as any of the base
RSA types while trying to decide on the key algorithm string _after_
replacing the certificate.

Fixed by reverting to the the uncertified base algorithm before
calling ssh_keyalg_related_alg.
2023-05-04 23:54:33 +01:00
Simon Tatham
70aabdc67c Fix segfault if SSH connection terminates very early.
Introduced in the previous commit. The new ssh_ppl_final_output method
shouldn't be called in any of the error cleanup functions if
ssh->base_layer is NULL, which it can be if we haven't got far enough
through the connection to set up any packet protocol layers at
all. (For example, ECONNREFUSED would do it.)
2023-05-04 23:54:22 +01:00
Simon Tatham
d51b30ef49 userauth: ensure banner output is printed when connection closes.
This should fix the bug mentioned three commits ago: if an SSH server
sends a userauth banner and then immediately slams the connection
shut (with or without SSH_MSG_DISCONNECT), the banner message should
now be reliably printed to the user, which is important if that's
where the server put its explanation for the disconnection (e.g. "Your
account has expired").

(cherry picked from commit e8becb45b5)
2023-05-04 23:54:08 +01:00
Simon Tatham
0dee089252 userauth: refactor banner handling.
No functional change: I've just pulled out into separate subroutines
the piece of code that process a USERAUTH_BANNER message and append
it to our banner bufchain, and the piece that prints the contents of
the bufchain as user output. This will enable them to be called from
additional places easily.

(cherry picked from commit 99bbbd8d32)
2023-05-04 23:54:04 +01:00
Simon Tatham
44272b5355 Packet protocol layers: new 'final_output' method.
This is called just before closing the connection, and gives every PPL
one last chance to output anything to the user that it might have
buffered.

No functional change: all implementations so far are trivial, except
that the transport layer passes the call on to its higher
layer (because otherwise nothing would do so).

(cherry picked from commit d6e6919f69)
2023-05-04 23:54:01 +01:00
Simon Tatham
7e8be5a204 Fix factor-of-1000 error in Unix bell overload config.
During the transition to cmake, commit b00e5fb129 renamed
unix/unix.h to unix/platform.h, and for visual consistency, also
renamed the guard macro PUTTY_UNIX_H to PUTTY_UNIX_PLATFORM_H.

But I had failed to notice that that guard macro is re-tested in
settings.c, as a convenient method of knowing whether we're building
the Windows or Unix version of PuTTY in order to store some settings
differently. So all those '#ifdef PUTTY_UNIX_H' statements silently
became equivalent to '#if 0', because PUTTY_UNIX_H is _never_ defined
any more.

Specifically, these ifdefs were causing the time intervals relating to
bell overloads to be off by a factor of 1000, because for some reason
I can't remember, we were storing those intervals using a different
time unit on Unix and Windows. In my own configuration, for example,
~/.putty/sessions/Default%20Settings contains "BellOverloadT=2000000"
and "BellOverloadS=5000000", which originally meant that too many
bells within 2 seconds would silence the bell until there were 5
seconds of silence - but current PuTTY shows it in the configurer as
2000 and 5000 seconds!

This commit belatedly rewrites the ifdefs in settings.c, so that saved
sessions from before 0.77 will now be interpreted correctly. Saved
sessions from after that may need a rewrite. (But you have to have one
or the other.)

(cherry picked from commit 62b69a4f16)
2023-05-04 23:53:57 +01:00
Simon Tatham
e8becb45b5 userauth: ensure banner output is printed when connection closes.
This should fix the bug mentioned three commits ago: if an SSH server
sends a userauth banner and then immediately slams the connection
shut (with or without SSH_MSG_DISCONNECT), the banner message should
now be reliably printed to the user, which is important if that's
where the server put its explanation for the disconnection (e.g. "Your
account has expired").
2023-04-29 11:37:40 +01:00
Simon Tatham
99bbbd8d32 userauth: refactor banner handling.
No functional change: I've just pulled out into separate subroutines
the piece of code that process a USERAUTH_BANNER message and append
it to our banner bufchain, and the piece that prints the contents of
the bufchain as user output. This will enable them to be called from
additional places easily.
2023-04-29 11:37:40 +01:00
Simon Tatham
d6e6919f69 Packet protocol layers: new 'final_output' method.
This is called just before closing the connection, and gives every PPL
one last chance to output anything to the user that it might have
buffered.

No functional change: all implementations so far are trivial, except
that the transport layer passes the call on to its higher
layer (because otherwise nothing would do so).
2023-04-29 11:37:40 +01:00
Simon Tatham
fe63b5d57e Uppity: add a stunt mode --close-after-banner.
A user reported yesterday that PuTTY can fail to print a userauth
banner message if the server sends one and then immediately slams the
connection shut. The first step to fixing this is making a convenient
way to reproduce that server behaviour.

(Apparently the real use case has to do with account expiry - the
server in question presumably doesn't have enough layer violations to
be able to put the text "Your account has expired" into an
SSH_MSG_DISCONNECT, so instead it does the next best thing and sends
it as a userauth banner immediately before disconnection.)
2023-04-29 11:34:08 +01:00
Simon Tatham
62b69a4f16 Fix factor-of-1000 error in Unix bell overload config.
During the transition to cmake, commit b00e5fb129 renamed
unix/unix.h to unix/platform.h, and for visual consistency, also
renamed the guard macro PUTTY_UNIX_H to PUTTY_UNIX_PLATFORM_H.

But I had failed to notice that that guard macro is re-tested in
settings.c, as a convenient method of knowing whether we're building
the Windows or Unix version of PuTTY in order to store some settings
differently. So all those '#ifdef PUTTY_UNIX_H' statements silently
became equivalent to '#if 0', because PUTTY_UNIX_H is _never_ defined
any more.

Specifically, these ifdefs were causing the time intervals relating to
bell overloads to be off by a factor of 1000, because for some reason
I can't remember, we were storing those intervals using a different
time unit on Unix and Windows. In my own configuration, for example,
~/.putty/sessions/Default%20Settings contains "BellOverloadT=2000000"
and "BellOverloadS=5000000", which originally meant that too many
bells within 2 seconds would silence the bell until there were 5
seconds of silence - but current PuTTY shows it in the configurer as
2000 and 5000 seconds!

This commit belatedly rewrites the ifdefs in settings.c, so that saved
sessions from before 0.77 will now be interpreted correctly. Saved
sessions from after that may need a rewrite. (But you have to have one
or the other.)
2023-04-26 10:59:38 +01:00
Simon Tatham
aa87c20716 Put HMAC-SHA-512 below HMAC-SHA-256 in priority.
For the same reason that diffie-hellman-group18 goes below group16:
it's useful to _have_ it there, in case a server demands it, but under
normal circumstances it seems like overkill and a waste of CPU.
SHA-256 is not only intrinsically faster, it's also more likely to be
hardware-accelerated, so PuTTY's preference is to use that if possible
and SHA-512 only if necessary.

(cherry picked from commit 289d123fb8)
2023-04-23 13:24:22 +01:00
Simon Tatham
f6f9848465 Add support for HMAC-SHA512.
I saw a post on comp.security.ssh just now where someone had
encountered an SSH server that would _only_ speak that, which makes it
worth bothering to implement.

The totally obvious implementation works, and passes the test cases
from RFC 6234.

(cherry picked from commit b77e985513)
2023-04-23 13:24:19 +01:00
Simon Tatham
289d123fb8 Put HMAC-SHA-512 below HMAC-SHA-256 in priority.
For the same reason that diffie-hellman-group18 goes below group16:
it's useful to _have_ it there, in case a server demands it, but under
normal circumstances it seems like overkill and a waste of CPU.
SHA-256 is not only intrinsically faster, it's also more likely to be
hardware-accelerated, so PuTTY's preference is to use that if possible
and SHA-512 only if necessary.
2023-04-22 00:07:51 +01:00
Simon Tatham
b77e985513 Add support for HMAC-SHA512.
I saw a post on comp.security.ssh just now where someone had
encountered an SSH server that would _only_ speak that, which makes it
worth bothering to implement.

The totally obvious implementation works, and passes the test cases
from RFC 6234.
2023-04-21 20:17:43 +01:00
Simon Tatham
c545c04102 Fix potential null-pointer dereference in ssh_reconfig.
ssh->base_layer is NULL when the connection is still in its early
stages, before greetings are exchanged. If the user invokes the Change
Settings dialog in this situation, ssh_reconfig would call
ssh_ppl_reconfigure() on ssh->base_layer without checking if it was
NULL first.

(cherry picked from commit d67c13eeb8)
2023-04-19 14:28:36 +01:00
Simon Tatham
f17daf6cc7 Remove a completely unused loop in RTF pasting.
In commit d07d7d66f6 I rewrote the code that constructs RTF paste
data so that it uses a strbuf, in place of the previous ad-hoc code
that counted up the lengths of pieces of RTF in advance in order to
realloc the buffer.

But apparently I left in an entire loop whose job was to count up one
of those lengths, failing to notice that it's now completely pointless
because its output value is never needed!

Happily a clang upgrade has just improved the 'variable set but not
used' warning to the point where it can spot that. I expect previously
the variable still counted as 'used' because each increment of it used
the previous value.

(cherry picked from commit 6a27ae772c)
2023-04-19 14:28:36 +01:00
Simon Tatham
c3aba5d959 Fix potential corruption when writing help file.
When the standalone version of a binary, with its help file included
as a resource, extracts that resource to write it to a disk, it could
have accidentally skipped a byte in the middle if the WriteFile call
in this loop had not managed to write the whole file in one go.

(cherry picked from commit 775d969ca8)
2023-04-19 14:28:36 +01:00
Simon Tatham
a02fd09854 Improve time-safety of XDM-AUTHORIZATION-1 validation.
While writing the previous patch, I realise that walking along a
decrypted string and stopping to complain about the first mismatch you
find is an anti-pattern. If we're going to deliberately give the same
error message for various mismatches, so as not to give away which
part failed first, then we should also avoid giving away the same
information via a timing leak!

I don't think this is serious enough to warrant the full-on advisory
protocol, because XDM-AUTHORIZATION-1 is rarely used these days and
also DES-based, so there are bigger problems with it. (Plus, why on
earth is it based on encryption anyway, not a MAC?) But since I
spotted it in passing, might as well fix it.

(cherry picked from commit 8e7e3c5944)
2023-04-19 14:28:36 +01:00
Simon Tatham
3f5873f1fe Improve error reporting from x11_verify().
Now the return value is a dynamically allocated string instead of a
static one, which means that the error message can include details
taken from the specific failing connection. In particular, if someone
requests an X11 authorisation protocol we don't support, we can print
its name as part of the message, which may help users debug the
problem.

One particularly important special case of this is that if the client
connection presents _no_ authorisation - which is surely by far the
most likely thing to happen by accident, e.g. if the auth file has
gone missing, or the hostname doesn't match for some reason - then we
now give a specific message "No authorisation provided", which I think
is considerably more helpful than just lumping that very common case
in with "Unsupported authorisation protocol". Even changing the latter
to "Unsupported authorisation protocol ''" is still not very sensible.
The problem in that case is not that the user has tried an exotic auth
protocol we've never heard of - it's that they've forgotten, or
failed, to provide one at all.

The error message for "XDM-AUTHORIZATION-1 data was wrong length" is
the other modified one: it now says what the wrong length _was_.
However, all other failures of X-A-1 are still kept deliberately
vague, because saying which part of the decrypted string didn't match
is an obvious information leak.

(cherry picked from commit dff4bd4d14)
2023-04-19 14:28:36 +01:00
Jacob Nevins
4d92ca80de Windows installer: restore InstallScope setting.
This reverts commit 0615767224
("Windows installer: remove explicit InstallScope setting"), albeit
with different comments.

The original change worked around a Windows security vulnerability
(CVE-2023-21800), but also resulted in a rather broken installer.

(cherry picked from commit cedeb75d59)
2023-04-19 14:28:36 +01:00
Simon Tatham
bdf7f73d3d split_into_argv: stop using isspace().
I checked exhaustively today and found that the only characters (even
in Unicode) that Windows's default argv splitter will recognise as
word separators are the space and tab characters. So I think it's a
mistake to use <ctype.h> functions to identify word separators; we
should use that fixed character pair, and then we know we're getting
the right ones only.

(cherry picked from commit 9adfa79767)
2023-04-19 14:28:36 +01:00
Simon Tatham
bece41ddb0 Add some missing casts in ctype functions.
I thought I'd found all of these before, but perhaps a few managed to
slip in since I last looked. The character argument to the <ctype.h>
functions must have the value of an unsigned char or EOF; passing an
ordinary char (unless you know char is unsigned on every platform the
code will ever go near) risks mistaking '\xFF' for EOF, and causing
outright undefined behaviour on byte values in the range 80-FE. Never
do it.

(cherry picked from commit a76109c586)
2023-04-19 14:28:36 +01:00
Simon Tatham
15081bb0ad Fix printing double-width char in rightmost column without wrap.
Another bug turned up by writing tests. The code that spots that the
character won't fit, and wraps it to the next line setting
LATTR_WRAPPED2, was not checking that wrap mode was _enabled_ before
doing that. So if you printed a DW character in the rightmost column
while the terminal was in non-auto-wrap mode, you'd get an unwanted
wrap.

Other terminals disagree on what to do here. xterm leaves the cursor
in the same place and doesn't print any character at all.
gnome-terminal, on the other hand, backspaces by a character so that
it _can_ print the requested DW character, in the rightmost _two_
columns.

I think I don't much like either of those, so instead I'm using the
same fallback we use for displaying a DW character when the whole
terminal is only one column wide: if there is physically no room to
print the requested character, turn it into U+FFFD REPLACEMENT
CHARACTER.

(cherry picked from commit ed5bf9b3b8)
2023-04-19 14:28:36 +01:00
Simon Tatham
8b8b774fc0 Fix behaviour of backspace in a 1-column terminal.
This is the first bug found as a direct result of writing that
terminal test program - I added some tests for things I expected to
work already, and some of them didn't, proving immediately that it was
a good idea!

If the terminal is one column wide, and you've printed a
character (hence, set the wrapnext flag), what should backspace do?
Surely it should behave like any other backspace with wrapnext set,
i.e. clear the wrapnext flag, returning the cursor's _logical_
position to the location of the most recently printed character. But
in fact it was anti-wrapping to the previous line, because I'd got the
cases in the wrong order in the if-else chain that forms the backspace
handler. So the handler for 'we're in column 0, wrapping time' was
coming before 'wrapnext is set, just clear it'.

Now wrapnext is checked _first_, before checking anything at all. Any
time we can just clear that, we should.

(cherry picked from commit 069f7c8b21)
2023-04-19 14:28:36 +01:00
Simon Tatham
05276bda5c Make backspace take account of LATTR_WRAPPED2.
Suppose an application tries to print a double-width character
starting in the rightmost column of the screen, so that we apply our
emergency fix of wrapping to the next line immediately and printing
the character in the first two columns. Suppose they then backspace
twice, taking the cursor to the RHS and then the LHS of that
character. What should happen if they backspace a third time?

Our previous behaviour was to completely ignore the unusual situation,
and do the same thing we'd do in any other backspace from column 0:
anti-wrap the cursor to the last column of the previous line, leaving
it in the empty character cell that was skipped when the DW char
couldn't be printed in it.

But I think this isn't the best response, because it breaks the
invariant that printing N columns' worth of graphic characters and
then backspacing N times should leave the cursor on the first of those
characters. If I print "a가" (for example) and then backspace three
times, I want the cursor on the a, _even_ if weird line wrapping
behaviour happened somewhere in that sequence.

(Rationale: this helps naïve terminal applications which don't even
know what the terminal width is, and aren't tracking their absolute x
position. In particular, the simplistic line-based input systems that
appear in OS kernels and our own lineedit.c will want to emit a fixed
number of backspace-space-backspace sequences to delete characters
previously entered on to the line by the user. They still need to
check the wcwidth of the characters they're emitting, so that they can
BSB twice for a DW character or 0 times for a combining one, but it
would be *hugely* more awkward for them to ask the terminal where the
cursor is so that they can take account of difficult line wraps!)

We already have the ability to _recognise_ this situation: on a line
that was wrapped in this unusual way, we set the LATTR_WRAPPED2 line
attribute flag, to prevent the empty rightmost column from injecting
an unwanted space into copy-pastes from the terminal. Now we also use
the same flag to cause the backspace control character to do something
interesting.

This was the fix that inspired me to start writing test_terminal,
because I knew it was touching a delicate area. However, in the course
of writing this fix and its tests, I encountered two (!) further bugs,
which I'll fix in followup commits!

(cherry picked from commit 9ba742ad9f)
2023-04-19 14:28:36 +01:00
Simon Tatham
407bf88a95 Document our long-standing workarounds policy.
For years I've been following the principle that before I'll add
auto-detection of an SSH server bug, I want the server maintainer to
have fixed the bug, so that the list of affected version numbers
triggering the workaround is complete, and to provide an incentive for
implementations to gradually converge on rightness.

*Finally*, I've got round to documenting that policy in public, for
the Feedback page!

(cherry picked from commit b5645f79dd)
2023-04-19 14:28:36 +01:00
Simon Tatham
5cac358f7f Reinstate putty.chm in Windows binary zipfiles.
A user just reported that it hasn't been there since 0.76. This turns
out to be because I put the wrong pathname on the 'zip' commands in
Buildscr (miscounted the number of ../ segments).

I would have noticed immediately, if Info-Zip had failed with an error
when it found I'd given it a nonexistent filename to add to the zip
file. But in fact it just prints a warning and proceeds to add all the
other files I specified. It looks as if it will only return a nonzero
exit status if _all_ the filenames you specified were nonexistent.

Therefore, I've rewritten the zip-creation commands so that they run
zip once per file. That way if any file is unreadable we _will_ get a
build error.

(Also, while I'm here, I took the opportunity to get rid of that ugly
ls|grep.)

(cherry picked from commit 9d308b39da)
2023-04-19 14:28:36 +01:00
Jacob Nevins
5e250745ea 'private key' -> 'SSH private key' in new FAQ.
(cherry picked from commit 343f64c2ca)
2023-04-19 14:28:36 +01:00
Simon Tatham
ae3c419ec1 Fix build failure on systems without fstatat.
cmake's configure-time #defines (at least the way I use them) are
defined to 0 or 1, rather than sometimes not defined at all, so you
have to test them with plain #if rather than #ifdef or #if defined.

I _thought_ I'd caught all of those in previous fixes, but apparently
there were a couple still lurking. Oops.

(cherry picked from commit e289265e37)
2023-04-19 14:28:36 +01:00
Jacob Nevins
ca331eeed7 It's a new year.
(cherry picked from commit 89014315ed)
2023-04-19 14:28:36 +01:00
Jacob Nevins
3c13ea6092 FAQ about private key configuration control move.
This is genuinely a FAQ -- we've been asked about it 3-4 times now.

(cherry picked from commit 943e54db4a)
2023-04-19 14:28:36 +01:00
Simon Tatham
1aa97cfb89 Another minor docs typo.
(cherry picked from commit 37f67bc937)
2023-04-19 14:28:36 +01:00