2018-05-24 07:59:01 +00:00
|
|
|
/*
|
|
|
|
* defs.h: initial definitions for PuTTY.
|
|
|
|
*
|
|
|
|
* The rule about this header file is that it can't depend on any
|
|
|
|
* other header file in this code base. This is where we define
|
|
|
|
* things, as much as we can, that other headers will want to refer
|
|
|
|
* to, such as opaque structure types and their associated typedefs,
|
|
|
|
* or macros that are used by other headers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef PUTTY_DEFS_H
|
|
|
|
#define PUTTY_DEFS_H
|
|
|
|
|
2021-04-10 13:46:36 +00:00
|
|
|
#ifdef NDEBUG
|
|
|
|
/*
|
|
|
|
* PuTTY is a security project, so assertions are important - if an
|
|
|
|
* assumption is violated, proceeding anyway may have far worse
|
|
|
|
* consequences than simple program termination. This check and #error
|
|
|
|
* should arrange that we don't ever accidentally compile assertions
|
|
|
|
* out.
|
|
|
|
*/
|
|
|
|
#error Do not compile this code base with NDEBUG defined!
|
|
|
|
#endif
|
|
|
|
|
2021-04-19 05:40:01 +00:00
|
|
|
#if HAVE_CMAKE_H
|
|
|
|
#include "cmake.h"
|
|
|
|
#endif
|
|
|
|
|
2018-05-27 15:56:51 +00:00
|
|
|
#include <stddef.h>
|
2018-10-26 22:08:58 +00:00
|
|
|
#include <stdint.h>
|
2021-04-02 12:10:14 +00:00
|
|
|
#include <stdio.h> /* for __MINGW_PRINTF_FORMAT */
|
2018-10-29 19:50:29 +00:00
|
|
|
#include <stdbool.h>
|
2018-10-26 22:08:58 +00:00
|
|
|
|
|
|
|
#if defined _MSC_VER && _MSC_VER < 1800
|
2019-06-19 05:49:24 +00:00
|
|
|
/* Work around lack of inttypes.h and strtoumax in older MSVC */
|
2018-11-22 07:05:58 +00:00
|
|
|
#define PRIx32 "x"
|
2020-02-15 16:39:02 +00:00
|
|
|
#define PRIu32 "u"
|
2018-10-26 22:08:58 +00:00
|
|
|
#define PRIu64 "I64u"
|
New test system for mp_int and cryptography.
I've written a new standalone test program which incorporates all of
PuTTY's crypto code, including the mp_int and low-level elliptic curve
layers but also going all the way up to the implementations of the
MAC, hash, cipher, public key and kex abstractions.
The test program itself, 'testcrypt', speaks a simple line-oriented
protocol on standard I/O in which you write the name of a function
call followed by some inputs, and it gives you back a list of outputs
preceded by a line telling you how many there are. Dynamically
allocated objects are assigned string ids in the protocol, and there's
a 'free' function that tells testcrypt when it can dispose of one.
It's possible to speak that protocol by hand, but cumbersome. I've
also provided a Python module that wraps it, by running testcrypt as a
persistent subprocess and gatewaying all the function calls into
things that look reasonably natural to call from Python. The Python
module and testcrypt.c both read a carefully formatted header file
testcrypt.h which contains the name and signature of every exported
function, so it costs minimal effort to expose a given function
through this test API. In a few cases it's necessary to write a
wrapper in testcrypt.c that makes the function look more friendly, but
mostly you don't even need that. (Though that is one of the
motivations between a lot of API cleanups I've done recently!)
I considered doing Python integration in the more obvious way, by
linking parts of the PuTTY code directly into a native-code .so Python
module. I decided against it because this way is more flexible: I can
run the testcrypt program on its own, or compile it in a way that
Python wouldn't play nicely with (I bet compiling just that .so with
Leak Sanitiser wouldn't do what you wanted when Python loaded it!), or
attach a debugger to it. I can even recompile testcrypt for a
different CPU architecture (32- vs 64-bit, or even running it on a
different machine over ssh or under emulation) and still layer the
nice API on top of that via the local Python interpreter. All I need
is a bidirectional data channel.
2019-01-01 19:08:37 +00:00
|
|
|
#define PRIdMAX "I64d"
|
|
|
|
#define PRIXMAX "I64X"
|
2018-10-26 22:08:58 +00:00
|
|
|
#define SCNu64 "I64u"
|
2020-01-26 10:59:07 +00:00
|
|
|
#define SIZEx "Ix"
|
|
|
|
#define SIZEu "Iu"
|
2019-06-19 05:49:24 +00:00
|
|
|
uintmax_t strtoumax(const char *nptr, char **endptr, int base);
|
2022-03-12 17:10:11 +00:00
|
|
|
/* Also, define a LEGACY_WINDOWS flag to enable other workarounds */
|
|
|
|
#define LEGACY_WINDOWS
|
2018-10-26 22:08:58 +00:00
|
|
|
#else
|
|
|
|
#include <inttypes.h>
|
2020-01-26 10:59:07 +00:00
|
|
|
/* Because we still support older MSVC libraries which don't recognise the
|
|
|
|
* standard C "z" modifier for size_t-sized integers, we must use an
|
|
|
|
* inttypes.h-style macro for those */
|
|
|
|
#define SIZEx "zx"
|
|
|
|
#define SIZEu "zu"
|
2018-10-26 22:08:58 +00:00
|
|
|
#endif
|
2018-05-27 15:56:51 +00:00
|
|
|
|
2020-01-26 14:49:31 +00:00
|
|
|
#if defined __GNUC__ || defined __clang__
|
|
|
|
/*
|
|
|
|
* On MinGW, the correct compiler format checking for vsnprintf() etc
|
|
|
|
* can depend on compile-time flags; these control whether you get
|
|
|
|
* ISO C or Microsoft's non-standard format strings.
|
|
|
|
* We sometimes use __attribute__ ((format)) for our own printf-like
|
|
|
|
* functions, which are ultimately interpreted by the toolchain-chosen
|
|
|
|
* printf, so we need to take that into account to get correct warnings.
|
|
|
|
*/
|
|
|
|
#ifdef __MINGW_PRINTF_FORMAT
|
|
|
|
#define PRINTF_LIKE(fmt_index, ellipsis_index) \
|
|
|
|
__attribute__ ((format (__MINGW_PRINTF_FORMAT, fmt_index, ellipsis_index)))
|
|
|
|
#else
|
|
|
|
#define PRINTF_LIKE(fmt_index, ellipsis_index) \
|
|
|
|
__attribute__ ((format (printf, fmt_index, ellipsis_index)))
|
|
|
|
#endif
|
|
|
|
#else /* __GNUC__ */
|
|
|
|
#define PRINTF_LIKE(fmt_index, ellipsis_index)
|
|
|
|
#endif /* __GNUC__ */
|
|
|
|
|
2018-05-24 07:59:01 +00:00
|
|
|
typedef struct conf_tag Conf;
|
|
|
|
typedef struct terminal_tag Terminal;
|
2019-03-04 20:53:41 +00:00
|
|
|
typedef struct term_utf8_decode term_utf8_decode;
|
2018-05-24 07:59:01 +00:00
|
|
|
|
|
|
|
typedef struct Filename Filename;
|
|
|
|
typedef struct FontSpec FontSpec;
|
|
|
|
|
|
|
|
typedef struct bufchain_tag bufchain;
|
|
|
|
|
|
|
|
typedef struct strbuf strbuf;
|
2020-02-02 11:27:03 +00:00
|
|
|
typedef struct LoadedFile LoadedFile;
|
2018-05-24 07:59:01 +00:00
|
|
|
|
2019-01-04 06:51:44 +00:00
|
|
|
typedef struct RSAKey RSAKey;
|
2018-05-24 07:59:01 +00:00
|
|
|
|
2018-05-24 08:17:13 +00:00
|
|
|
typedef struct BinarySink BinarySink;
|
Introduce a centralised unmarshaller, 'BinarySource'.
This is the companion to the BinarySink system I introduced a couple
of weeks ago, and provides the same type-genericity which will let me
use the same get_* routines on an SSH packet, an SFTP packet or
anything else that chooses to include an implementing substructure.
However, unlike BinarySink which contained a (one-function) vtable,
BinarySource contains only mutable data fields - so another thing you
might very well want to do is to simply instantiate a bare one without
any containing object at all. I couldn't quite coerce C into letting
me use the same setup macro in both cases, so I've arranged a
BinarySource_INIT you can use on larger implementing objects and a
BinarySource_BARE_INIT you can use on a BinarySource not contained in
anything.
The API follows the general principle that even if decoding fails, the
decode functions will always return _some_ kind of value, with the
same dynamically-allocated-ness they would have used for a completely
successful value. But they also set an error flag in the BinarySource
which can be tested later. So instead of having to decode a 10-field
packet by means of 10 separate 'if (!get_foo(src)) throw error'
clauses, you can just write 10 'variable = get_foo(src)' statements
followed by a single check of get_err(src), and if the error check
fails, you have to do exactly the same set of frees you would have
after a successful decode.
2018-06-02 07:25:19 +00:00
|
|
|
typedef struct BinarySource BinarySource;
|
2019-02-20 06:52:54 +00:00
|
|
|
typedef struct stdio_sink stdio_sink;
|
|
|
|
typedef struct bufchain_sink bufchain_sink;
|
|
|
|
typedef struct handle_sink handle_sink;
|
2018-05-24 08:17:13 +00:00
|
|
|
|
2018-09-23 15:35:29 +00:00
|
|
|
typedef struct IdempotentCallback IdempotentCallback;
|
|
|
|
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
typedef struct SockAddr SockAddr;
|
2018-05-27 08:29:33 +00:00
|
|
|
|
2018-10-05 06:24:16 +00:00
|
|
|
typedef struct Socket Socket;
|
|
|
|
typedef struct Plug Plug;
|
2018-10-18 19:06:42 +00:00
|
|
|
typedef struct SocketPeerInfo SocketPeerInfo;
|
Allow creating FdSocket/HandleSocket before the fds/handles.
Previously, a setup function returning one of these socket types (such
as platform_new_connection) had to do all its setup synchronously,
because if it was going to call make_fd_socket or make_handle_socket,
it had to have the actual fds or HANDLEs ready-made. If some kind of
asynchronous operation were needed before those fds become available,
there would be no way the function could achieve it, except by
becoming a whole extra permanent Socket wrapper layer.
Now there is, because you can make an FdSocket when you don't yet have
the fds, or a HandleSocket without the HANDLEs. Instead, you provide
an instance of the new trait 'DeferredSocketOpener', which is
responsible for setting in motion whatever asynchronous setup
procedure it needs, and when that finishes, calling back to
setup_fd_socket / setup_handle_socket to provide the missing pieces.
In the meantime, the FdSocket or HandleSocket will sit there inertly,
buffering any data the client might eagerly hand it via sk_write(),
and waiting for its setup to finish. When it does finish, buffered
data will be released.
In FdSocket, this is easy enough, because we were doing our own
buffering anyway - we called the uxsel system to find out when the fds
were readable/writable, and then wrote to them from our own bufchain.
So more or less all I had to do was make the try_send function do
nothing if the setup phase wasn't finished yet.
In HandleSocket, on the other hand, we're passing all our data to the
underlying handle-io.c system, and making _that_ deferrable in the
same way would be much more painful, because that's the place where
the scary threads live. So instead I've arranged it by replacing the
whole vtable, so that a deferred HandleSocket and a normal
HandleSocket are effectively separate trait implementations that can
share their state structure. And in fact that state struct itself now
contains a big anonymous union, containing one branch to go with each
vtable.
Nothing yet uses this system, but the next commit will do so.
2021-12-22 09:31:06 +00:00
|
|
|
typedef struct DeferredSocketOpener DeferredSocketOpener;
|
|
|
|
typedef struct DeferredSocketOpenerVtable DeferredSocketOpenerVtable;
|
2018-05-27 08:29:33 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
typedef struct Backend Backend;
|
2018-10-05 06:03:46 +00:00
|
|
|
typedef struct BackendVtable BackendVtable;
|
Introduce a new 'Interactor' trait.
This trait will be implemented by anything that wants to display
interactive prompts or notifications to the user in the course of
setting up a network connection, _or_ anything that wants to make a
network connection whose proxy setup might in turn need to do that.
To begin with, that means every Backend that makes network connections
at all must be an Interactor, because any of those network connections
might be proxied via an SSH jump host which might need to interact
with the user.
I'll fill in the contents of this trait over the next few commits, to
keep the patches comprehensible. For the moment, I've just introduced
the trait, set up implementations of it in the five network backends,
and given it a single 'description' method.
The previous 'description' methods of Backend and Plug are now
removed, and their work is done by the new Interactor method instead.
(I changed my mind since last week about where that should best live.)
This isn't too much of an upheaval, fortunately, because I hadn't got
round yet to committing anything that used those methods!
2021-10-30 16:16:08 +00:00
|
|
|
typedef struct Interactor Interactor;
|
|
|
|
typedef struct InteractorVtable InteractorVtable;
|
Framework for announcing which Interactor is talking.
All this Interactor business has been gradually working towards being
able to inform the user _which_ network connection is currently
presenting them with a password prompt (or whatever), in situations
where more than one of them might be, such as an SSH connection being
used as a proxy for another SSH connection when neither one has
one-touch login configured.
At some point, we have to arrange that any attempt to do a user
interaction during connection setup - be it a password prompt, a host
key confirmation dialog, or just displaying an SSH login banner -
makes it clear which host it's come from. That's going to mean calling
some kind of announcement function before doing any of those things.
But there are several of those functions in the Seat API, and calls to
them are scattered far and wide across the SSH backend. (And not even
just there - the Rlogin backend also uses seat_get_userpass_input).
How can we possibly make sure we don't forget a vital call site on
some obscure little-tested code path, and leave the user confused in
just that one case which nobody might notice for years?
Today I thought of a trick to solve that problem. We can use the C
type system to enforce it for us!
The plan is: we invent a new struct type which contains nothing but a
'Seat *'. Then, for every Seat method which does a thing that ought to
be clearly identified as relating to a particular Interactor, we
adjust the API for that function to take the new struct type where it
previously took a plain 'Seat *'. Or rather - doing less violence to
the existing code - we only need to adjust the API of the dispatch
functions inline in putty.h.
How does that help? Because the way you _get_ one of these
struct-wrapped Seat pointers is by calling interactor_announce() on
your Interactor, which will in turn call interactor_get_seat(), and
wrap the returned pointer into one of these structs.
The effect is that whenever the SSH (or Rlogin) code wants to call one
of those particular Seat methods, it _has_ to call
interactor_announce() just beforehand, which (once I finish all of
this) will make sure the user is aware of who is presenting the prompt
or banner or whatever. And you can't forget to call it, because if you
don't call it, then you just don't have a struct of the right type to
give to the Seat method you wanted to call!
(Of course, there's nothing stopping code from _deliberately_ taking a
Seat * it already has and wrapping it into the new struct. In fact
SshProxy has to do that, in order to forward these requests up the
chain of Seats. But the point is that you can't do it _by accident_,
just by forgetting to make a vital function call - when you do that,
you _know_ you're doing it on purpose.)
No functional change: the new interactor_announce() function exists,
and the type-system trick ensures it's called in all the right places,
but it doesn't actually _do_ anything yet.
2021-10-30 17:05:36 +00:00
|
|
|
typedef struct InteractionReadySeat InteractionReadySeat;
|
2018-09-11 15:23:38 +00:00
|
|
|
|
2018-09-11 14:02:59 +00:00
|
|
|
typedef struct Ldisc_tag Ldisc;
|
Refactor the LogContext type.
LogContext is now the owner of the logevent() function that back ends
and so forth are constantly calling. Previously, logevent was owned by
the Frontend, which would store the message into its list for the GUI
Event Log dialog (or print it to standard error, or whatever) and then
pass it _back_ to LogContext to write to the currently open log file.
Now it's the other way round: LogContext gets the message from the
back end first, writes it to its log file if it feels so inclined, and
communicates it back to the front end.
This means that lots of parts of the back end system no longer need to
have a pointer to a full-on Frontend; the only thing they needed it
for was logging, so now they just have a LogContext (which many of
them had to have anyway, e.g. for logging SSH packets or session
traffic).
LogContext itself also doesn't get a full Frontend pointer any more:
it now talks back to the front end via a little vtable of its own
called LogPolicy, which contains the method that passes Event Log
entries through, the old askappend() function that decides whether to
truncate a pre-existing log file, and an emergency function for
printing an especially prominent message if the log file can't be
created. One minor nice effect of this is that console and GUI apps
can implement that last function subtly differently, so that Unix
console apps can write it with a plain \n instead of the \r\n
(harmless but inelegant) that the old centralised implementation
generated.
One other consequence of this is that the LogContext has to be
provided to backend_init() so that it's available to backends from the
instant of creation, rather than being provided via a separate API
call a couple of function calls later, because backends have typically
started doing things that need logging (like making network
connections) before the call to backend_provide_logctx. Fortunately,
there's no case in the whole code base where we don't already have
logctx by the time we make a backend (so I don't actually remember why
I ever delayed providing one). So that shortens the backend API by one
function, which is always nice.
While I'm tidying up, I've also moved the printf-style logeventf() and
the handy logevent_and_free() into logging.c, instead of having copies
of them scattered around other places. This has also let me remove
some stub functions from a couple of outlying applications like
Pageant. Finally, I've removed the pointless "_tag" at the end of
LogContext's official struct name.
2018-10-10 18:26:18 +00:00
|
|
|
typedef struct LogContext LogContext;
|
|
|
|
typedef struct LogPolicy LogPolicy;
|
|
|
|
typedef struct LogPolicyVtable LogPolicyVtable;
|
2018-09-11 14:02:59 +00:00
|
|
|
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
typedef struct Seat Seat;
|
|
|
|
typedef struct SeatVtable SeatVtable;
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
typedef struct SeatPromptResult SeatPromptResult;
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
typedef struct TermWin TermWin;
|
|
|
|
typedef struct TermWinVtable TermWinVtable;
|
2018-09-12 08:10:51 +00:00
|
|
|
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
typedef struct Ssh Ssh;
|
2018-09-11 15:23:38 +00:00
|
|
|
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
typedef struct mp_int mp_int;
|
|
|
|
typedef struct MontyContext MontyContext;
|
|
|
|
|
|
|
|
typedef struct WeierstrassCurve WeierstrassCurve;
|
|
|
|
typedef struct WeierstrassPoint WeierstrassPoint;
|
|
|
|
typedef struct MontgomeryCurve MontgomeryCurve;
|
|
|
|
typedef struct MontgomeryPoint MontgomeryPoint;
|
|
|
|
typedef struct EdwardsCurve EdwardsCurve;
|
|
|
|
typedef struct EdwardsPoint EdwardsPoint;
|
|
|
|
|
2019-03-28 18:29:13 +00:00
|
|
|
typedef struct SshServerConfig SshServerConfig;
|
Add an SFTP server to the SSH server code.
Unlike the traditional Unix SSH server organisation, the SFTP server
is built into the same process as all the rest of the code. sesschan.c
spots a subsystem request for "sftp", and responds to it by
instantiating an SftpServer object and swapping out its own vtable for
one that talks to it.
(I rather like the idea of an object swapping its own vtable for a
different one in the middle of its lifetime! This is one of those
tricks that would be absurdly hard to implement in a 'proper' OO
language, but when you're doing vtables by hand in C, it's no more
difficult than any other piece of ordinary pointer manipulation. As
long as the methods in both vtables expect the same physical structure
layout, it doesn't cause a problem.)
The SftpServer object doesn't deal directly with SFTP packet formats;
it implements the SFTP server logic in a more abstract way, by having
a vtable method for each SFTP request type with an appropriate
parameter list. It sends its replies by calling methods in another
vtable called SftpReplyBuilder, which in the normal case will write an
SFTP reply packet to send back to the client. So SftpServer can focus
more or less completely on the details of a particular filesystem API
- and hence, the implementation I've got lives in the unix source
directory, and works directly with file descriptors and struct stat
and the like.
(One purpose of this abstraction layer is that I may well want to
write a second dummy implementation, for test-suite purposes, with
completely controllable behaviour, and now I have a handy place to
plug it in in place of the live filesystem.)
In between sesschan's parsing of the byte stream into SFTP packets and
the SftpServer object, there's a layer in the new file sftpserver.c
which does the actual packet decoding and encoding: each request
packet is passed to that, which pulls the fields out of the request
packet and calls the appropriate method of SftpServer. It also
provides the default SftpReplyBuilder which makes the output packet.
I've moved some code out of the previous SFTP client implementation -
basic packet construction code, and in particular the BinarySink/
BinarySource marshalling fuinction for fxp_attrs - into sftpcommon.c,
so that the two directions can share as much as possible.
2018-10-20 21:10:32 +00:00
|
|
|
typedef struct SftpServer SftpServer;
|
|
|
|
typedef struct SftpServerVtable SftpServerVtable;
|
|
|
|
|
Replace enum+union of local channel types with a vtable.
There's now an interface called 'Channel', which handles the local
side of an SSH connection-layer channel, in terms of knowing where to
send incoming channel data to, whether to close the channel, etc.
Channel and the previous 'struct ssh_channel' mutually refer. The
latter contains all the SSH-specific parts, and as much of the common
logic as possible: in particular, Channel doesn't have to know
anything about SSH packet formats, or which SSH protocol version is in
use, or deal with all the fiddly stuff about window sizes - with the
exception that x11fwd.c's implementation of it does have to be able to
ask for a small fixed initial window size for the bodgy system that
distinguishes upstream from downstream X forwardings.
I've taken the opportunity to move the code implementing the detailed
behaviour of agent forwarding out of ssh.c, now that all of it is on
the far side of a uniform interface. (This also means that if I later
implement agent forwarding directly to a Unix socket as an
alternative, it'll be a matter of changing just the one call to
agentf_new() that makes the Channel to plug into a forwarding.)
2018-09-12 14:03:47 +00:00
|
|
|
typedef struct Channel Channel;
|
2018-09-14 12:47:13 +00:00
|
|
|
typedef struct SshChannel SshChannel;
|
2018-09-30 06:16:38 +00:00
|
|
|
typedef struct mainchan mainchan;
|
Replace enum+union of local channel types with a vtable.
There's now an interface called 'Channel', which handles the local
side of an SSH connection-layer channel, in terms of knowing where to
send incoming channel data to, whether to close the channel, etc.
Channel and the previous 'struct ssh_channel' mutually refer. The
latter contains all the SSH-specific parts, and as much of the common
logic as possible: in particular, Channel doesn't have to know
anything about SSH packet formats, or which SSH protocol version is in
use, or deal with all the fiddly stuff about window sizes - with the
exception that x11fwd.c's implementation of it does have to be able to
ask for a small fixed initial window size for the bodgy system that
distinguishes upstream from downstream X forwardings.
I've taken the opportunity to move the code implementing the detailed
behaviour of agent forwarding out of ssh.c, now that all of it is on
the far side of a uniform interface. (This also means that if I later
implement agent forwarding directly to a Unix socket as an
alternative, it'll be a matter of changing just the one call to
agentf_new() that makes the Channel to plug into a forwarding.)
2018-09-12 14:03:47 +00:00
|
|
|
|
2018-09-13 08:09:10 +00:00
|
|
|
typedef struct ssh_sharing_state ssh_sharing_state;
|
|
|
|
typedef struct ssh_sharing_connstate ssh_sharing_connstate;
|
|
|
|
typedef struct share_channel share_channel;
|
|
|
|
|
2018-09-14 16:04:39 +00:00
|
|
|
typedef struct PortFwdManager PortFwdManager;
|
|
|
|
typedef struct PortFwdRecord PortFwdRecord;
|
2018-09-17 11:14:00 +00:00
|
|
|
typedef struct ConnectionLayer ConnectionLayer;
|
2018-09-14 16:04:39 +00:00
|
|
|
|
Replace PuTTY's PRNG with a Fortuna-like system.
This tears out the entire previous random-pool system in sshrand.c. In
its place is a system pretty close to Ferguson and Schneier's
'Fortuna' generator, with the main difference being that I use SHA-256
instead of AES for the generation side of the system (rationale given
in comment).
The PRNG implementation lives in sshprng.c, and defines a self-
contained data type with no state stored outside the object, so you
can instantiate however many of them you like. The old sshrand.c still
exists, but in place of the previous random pool system, it's just
become a client of sshprng.c, whose job is to hold a single global
instance of the PRNG type, and manage its reference count, save file,
noise-collection timers and similar administrative business.
Advantages of this change include:
- Fortuna is designed with a more varied threat model in mind than my
old home-grown random pool. For example, after any request for
random numbers, it automatically re-seeds itself, so that if the
state of the PRNG should be leaked, it won't give enough
information to find out what past outputs _were_.
- The PRNG type can be instantiated with any hash function; the
instance used by the main tools is based on SHA-256, an improvement
on the old pool's use of SHA-1.
- The new PRNG only uses the completely standard interface to the
hash function API, instead of having to have privileged access to
the internal SHA-1 block transform function. This will make it
easier to revamp the hash code in general, and also it means that
hardware-accelerated versions of SHA-256 will automatically be used
for the PRNG as well as for everything else.
- The new PRNG can be _tested_! Because it has an actual (if not
quite explicit) specification for exactly what the output numbers
_ought_ to be derived from the hashes of, I can (and have) put
tests in cryptsuite that ensure the output really is being derived
in the way I think it is. The old pool could have been returning
any old nonsense and it would have been very hard to tell for sure.
2019-01-22 22:42:41 +00:00
|
|
|
typedef struct prng prng;
|
2019-01-04 06:51:44 +00:00
|
|
|
typedef struct ssh_hashalg ssh_hashalg;
|
|
|
|
typedef struct ssh_hash ssh_hash;
|
|
|
|
typedef struct ssh_kex ssh_kex;
|
|
|
|
typedef struct ssh_kexes ssh_kexes;
|
|
|
|
typedef struct ssh_keyalg ssh_keyalg;
|
|
|
|
typedef struct ssh_key ssh_key;
|
|
|
|
typedef struct ssh_compressor ssh_compressor;
|
|
|
|
typedef struct ssh_decompressor ssh_decompressor;
|
|
|
|
typedef struct ssh_compression_alg ssh_compression_alg;
|
|
|
|
typedef struct ssh2_userkey ssh2_userkey;
|
|
|
|
typedef struct ssh2_macalg ssh2_macalg;
|
|
|
|
typedef struct ssh2_mac ssh2_mac;
|
Merge the ssh1_cipher type into ssh2_cipher.
The aim of this reorganisation is to make it easier to test all the
ciphers in PuTTY in a uniform way. It was inconvenient that there were
two separate vtable systems for the ciphers used in SSH-1 and SSH-2
with different functionality.
Now there's only one type, called ssh_cipher. But really it's the old
ssh2_cipher, just renamed: I haven't made any changes to the API on
the SSH-2 side. Instead, I've removed ssh1_cipher completely, and
adapted the SSH-1 BPP to use the SSH-2 style API.
(The relevant differences are that ssh1_cipher encapsulated both the
sending and receiving directions in one object - so now ssh1bpp has to
make a separate cipher instance per direction - and that ssh1_cipher
automatically initialised the IV to all zeroes, which ssh1bpp now has
to do by hand.)
The previous ssh1_cipher vtable for single-DES has been removed
completely, because when converted into the new API it became
identical to the SSH-2 single-DES vtable; so now there's just one
vtable for DES-CBC which works in both protocols. The other two SSH-1
ciphers each had to stay separate, because 3DES is completely
different between SSH-1 and SSH-2 (three layers of CBC structure
versus one), and Blowfish varies in endianness and key length between
the two.
(Actually, while I'm here, I've only just noticed that the SSH-1
Blowfish cipher mis-describes itself in log messages as Blowfish-128.
In fact it passes the whole of the input key buffer, which has length
SSH1_SESSION_KEY_LENGTH == 32 bytes == 256 bits. So it's actually
Blowfish-256, and has been all along!)
2019-01-17 18:06:08 +00:00
|
|
|
typedef struct ssh_cipheralg ssh_cipheralg;
|
|
|
|
typedef struct ssh_cipher ssh_cipher;
|
2019-01-04 06:51:44 +00:00
|
|
|
typedef struct ssh2_ciphers ssh2_ciphers;
|
|
|
|
typedef struct dh_ctx dh_ctx;
|
|
|
|
typedef struct ecdh_key ecdh_key;
|
2022-04-14 06:04:33 +00:00
|
|
|
typedef struct ecdh_keyalg ecdh_keyalg;
|
Implement OpenSSH 9.x's NTRU Prime / Curve25519 kex.
This consists of DJB's 'Streamlined NTRU Prime' quantum-resistant
cryptosystem, currently in round 3 of the NIST post-quantum key
exchange competition; it's run in parallel with ordinary Curve25519,
and generates a shared secret combining the output of both systems.
(Hence, even if you don't trust this newfangled NTRU Prime thing at
all, it's at least no _less_ secure than the kex you were using
already.)
As the OpenSSH developers point out, key exchange is the most urgent
thing to make quantum-resistant, even before working quantum computers
big enough to break crypto become available, because a break of the
kex algorithm can be applied retroactively to recordings of your past
sessions. By contrast, authentication is a real-time protocol, and can
only be broken by a quantum computer if there's one available to
attack you _already_.
I've implemented both sides of the mechanism, so that PuTTY and Uppity
both support it. In my initial testing, the two sides can both
interoperate with the appropriate half of OpenSSH, and also (of
course, but it would be embarrassing to mess it up) with each other.
2022-04-15 16:19:47 +00:00
|
|
|
typedef struct NTRUKeyPair NTRUKeyPair;
|
|
|
|
typedef struct NTRUEncodeSchedule NTRUEncodeSchedule;
|
2019-01-04 06:51:44 +00:00
|
|
|
|
2018-09-13 11:58:44 +00:00
|
|
|
typedef struct dlgparam dlgparam;
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
typedef struct dlgcontrol dlgcontrol;
|
2018-09-13 11:58:44 +00:00
|
|
|
|
2018-09-14 07:45:42 +00:00
|
|
|
typedef struct settings_w settings_w;
|
|
|
|
typedef struct settings_r settings_r;
|
|
|
|
typedef struct settings_e settings_e;
|
Initial support for host certificates.
Now we offer the OpenSSH certificate key types in our KEXINIT host key
algorithm list, so that if the server has a certificate, they can send
it to us.
There's a new storage.h abstraction for representing a list of trusted
host CAs, and which ones are trusted to certify hosts for what
domains. This is stored outside the normal saved session data, because
the whole point of host certificates is to avoid per-host faffing.
Configuring this set of trusted CAs is done via a new GUI dialog box,
separate from the main PuTTY config box (because it modifies a single
set of settings across all saved sessions), which you can launch by
clicking a button in the 'Host keys' pane. The GUI is pretty crude for
the moment, and very much at a 'just about usable' stage right now. It
will want some polishing.
If we have no CA configured that matches the hostname, we don't offer
to receive certified host keys in the first place. So for existing
users who haven't set any of this up yet, nothing will immediately
change.
Currently, if we do offer to receive certified host keys and the
server presents one signed by a CA we don't trust, PuTTY will bomb out
unconditionally with an error, instead of offering a confirmation box.
That's an unfinished part which I plan to fix before this goes into a
release.
2022-04-22 11:07:24 +00:00
|
|
|
typedef struct host_ca host_ca;
|
|
|
|
typedef struct host_ca_enum host_ca_enum;
|
2018-09-14 07:45:42 +00:00
|
|
|
|
Rework special-commands system to add an integer argument.
In order to list cross-certifiable host keys in the GUI specials menu,
the SSH backend has been inventing new values on the end of the
Telnet_Special enumeration, starting from the value TS_LOCALSTART.
This is inelegant, and also makes it awkward to break up special
handlers (e.g. to dispatch different specials to different SSH
layers), since if all you know about a special is that it's somewhere
in the TS_LOCALSTART+n space, you can't tell what _general kind_ of
thing it is. Also, if I ever need another open-ended set of specials
in future, I'll have to remember which TS_LOCALSTART+n codes are in
which set.
So here's a revamp that causes every special to take an extra integer
argument. For all previously numbered specials, this argument is
passed as zero and ignored, but there's a new main special code for
SSH host key cross-certification, in which the integer argument is an
index into the backend's list of available keys. TS_LOCALSTART is now
a thing of the past: if I need any other open-ended sets of specials
in future, I can add a new top-level code with a nicely separated
space of arguments.
While I'm at it, I've removed the legacy misnomer 'Telnet_Special'
from the code completely; the enum is now SessionSpecialCode, the
struct containing full details of a menu entry is SessionSpecial, and
the enum values now start SS_ rather than TS_.
2018-09-24 08:35:52 +00:00
|
|
|
typedef struct SessionSpecial SessionSpecial;
|
|
|
|
|
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 06:56:40 +00:00
|
|
|
typedef struct StripCtrlChars StripCtrlChars;
|
|
|
|
|
2021-10-10 13:40:51 +00:00
|
|
|
typedef struct BidiContext BidiContext;
|
|
|
|
|
2018-05-27 15:56:51 +00:00
|
|
|
/*
|
|
|
|
* A small structure wrapping up a (pointer, length) pair so that it
|
|
|
|
* can be conveniently passed to or from a function.
|
|
|
|
*/
|
|
|
|
typedef struct ptrlen {
|
|
|
|
const void *ptr;
|
|
|
|
size_t len;
|
|
|
|
} ptrlen;
|
|
|
|
|
2018-06-09 08:00:11 +00:00
|
|
|
typedef struct logblank_t logblank_t;
|
|
|
|
|
2018-09-21 15:53:45 +00:00
|
|
|
typedef struct BinaryPacketProtocol BinaryPacketProtocol;
|
Move most of ssh.c out into separate source files.
I've tried to separate out as many individually coherent changes from
this work as I could into their own commits, but here's where I run
out and have to commit the rest of this major refactoring as a
big-bang change.
Most of ssh.c is now no longer in ssh.c: all five of the main
coroutines that handle layers of the SSH-1 and SSH-2 protocols now
each have their own source file to live in, and a lot of the
supporting functions have moved into the appropriate one of those too.
The new abstraction is a vtable called 'PacketProtocolLayer', which
has an input and output packet queue. Each layer's main coroutine is
invoked from the method ssh_ppl_process_queue(), which is usually
(though not exclusively) triggered automatically when things are
pushed on the input queue. In SSH-2, the base layer is the transport
protocol, and it contains a pair of subsidiary queues by which it
passes some of its packets to the higher SSH-2 layers - first userauth
and then connection, which are peers at the same level, with the
former abdicating in favour of the latter at the appropriate moment.
SSH-1 is simpler: the whole login phase of the protocol (crypto setup
and authentication) is all in one module, and since SSH-1 has no
repeat key exchange, that setup layer abdicates in favour of the
connection phase when it's done.
ssh.c itself is now about a tenth of its old size (which all by itself
is cause for celebration!). Its main job is to set up all the layers,
hook them up to each other and to the BPP, and to funnel data back and
forth between that collection of modules and external things such as
the network and the terminal. Once it's set up a collection of packet
protocol layers, it communicates with them partly by calling methods
of the base layer (and if that's ssh2transport then it will delegate
some functionality to the corresponding methods of its higher layer),
and partly by talking directly to the connection layer no matter where
it is in the stack by means of the separate ConnectionLayer vtable
which I introduced in commit 8001dd4cb, and to which I've now added
quite a few extra methods replacing services that used to be internal
function calls within ssh.c.
(One effect of this is that the SSH-1 and SSH-2 channel storage is now
no longer shared - there are distinct struct types ssh1_channel and
ssh2_channel. That means a bit more code duplication, but on the plus
side, a lot fewer confusing conditionals in the middle of half-shared
functions, and less risk of a piece of SSH-1 escaping into SSH-2 or
vice versa, which I remember has happened at least once in the past.)
The bulk of this commit introduces the five new source files, their
common header sshppl.h and some shared supporting routines in
sshcommon.c, and rewrites nearly all of ssh.c itself. But it also
includes a couple of other changes that I couldn't separate easily
enough:
Firstly, there's a new handling for socket EOF, in which ssh.c sets an
'input_eof' flag in the BPP, and that responds by checking a flag that
tells it whether to report the EOF as an error or not. (This is the
main reason for those new BPP_READ / BPP_WAITFOR macros - they can
check the EOF flag every time the coroutine is resumed.)
Secondly, the error reporting itself is changed around again. I'd
expected to put some data fields in the public PacketProtocolLayer
structure that it could set to report errors in the same way as the
BPPs have been doing, but in the end, I decided propagating all those
data fields around was a pain and that even the BPPs shouldn't have
been doing it that way. So I've reverted to a system where everything
calls back to functions in ssh.c itself to report any connection-
ending condition. But there's a new family of those functions,
categorising the possible such conditions by semantics, and each one
has a different set of detailed effects (e.g. how rudely to close the
network connection, what exit status should be passed back to the
whole application, whether to send a disconnect message and/or display
a GUI error box).
I don't expect this to be immediately perfect: of course, the code has
been through a big upheaval, new bugs are expected, and I haven't been
able to do a full job of testing (e.g. I haven't tested every auth or
kex method). But I've checked that it _basically_ works - both SSH
protocols, all the different kinds of forwarding channel, more than
one auth method, Windows and Linux, connection sharing - and I think
it's now at the point where the easiest way to find further bugs is to
let it out into the wild and see what users can spot.
2018-09-24 17:28:16 +00:00
|
|
|
typedef struct PacketProtocolLayer PacketProtocolLayer;
|
2018-09-21 15:53:45 +00:00
|
|
|
|
2022-03-12 16:57:51 +00:00
|
|
|
struct unicode_data;
|
|
|
|
|
2018-05-24 07:59:01 +00:00
|
|
|
/* Do a compile-time type-check of 'to_check' (without evaluating it),
|
|
|
|
* as a side effect of returning the value 'to_return'. Note that
|
|
|
|
* although this macro double-*expands* to_return, it always
|
|
|
|
* *evaluates* exactly one copy of it, so it's side-effect safe. */
|
|
|
|
#define TYPECHECK(to_check, to_return) \
|
|
|
|
(sizeof(to_check) ? (to_return) : (to_return))
|
|
|
|
|
2018-05-24 13:55:10 +00:00
|
|
|
/* Return a pointer to the object of structure type 'type' whose field
|
|
|
|
* with name 'field' is pointed at by 'object'. */
|
2018-10-05 22:49:08 +00:00
|
|
|
#define container_of(object, type, field) \
|
2018-05-24 13:55:10 +00:00
|
|
|
TYPECHECK(object == &((type *)0)->field, \
|
|
|
|
((type *)(((char *)(object)) - offsetof(type, field))))
|
|
|
|
|
2018-12-01 10:33:08 +00:00
|
|
|
#if defined __GNUC__ || defined __clang__
|
|
|
|
#define NORETURN __attribute__((__noreturn__))
|
2021-04-10 10:51:08 +00:00
|
|
|
#elif defined _MSC_VER
|
|
|
|
#define NORETURN __declspec(noreturn)
|
2018-12-01 10:33:08 +00:00
|
|
|
#else
|
|
|
|
#define NORETURN
|
|
|
|
#endif
|
|
|
|
|
2021-11-24 19:02:40 +00:00
|
|
|
/*
|
|
|
|
* Standard macro definitions. STR() behaves like the preprocessor
|
|
|
|
* stringification # operator, and CAT() behaves like the token paste
|
|
|
|
* ## operator, except that each one macro-expands its argument(s)
|
|
|
|
* first, unlike the raw version. E.g.
|
|
|
|
*
|
|
|
|
* #__LINE__ -> "__LINE__"
|
|
|
|
* STR(__LINE__) -> "1234" (or whatever)
|
|
|
|
*
|
|
|
|
* and similarly,
|
|
|
|
*
|
|
|
|
* foo ## __LINE__ -> foo__LINE__
|
|
|
|
* CAT(foo, __LINE__) -> foo1234 (or whatever)
|
|
|
|
*
|
|
|
|
* The expansion is achieved by having each macro pass its arguments
|
|
|
|
* to a secondary inner macro, because parameter lists of a macro call
|
|
|
|
* get expanded before the called macro is invoked. So STR(__LINE__)
|
|
|
|
* -> STR_INNER(1234) -> #1234 -> "1234", and similarly for CAT.
|
|
|
|
*/
|
|
|
|
#define STR_INNER(x) #x
|
|
|
|
#define STR(x) STR_INNER(x)
|
|
|
|
#define CAT_INNER(x,y) x ## y
|
|
|
|
#define CAT(x,y) CAT_INNER(x,y)
|
|
|
|
|
2018-05-24 07:59:01 +00:00
|
|
|
#endif /* PUTTY_DEFS_H */
|