2018-05-24 10:59:01 +03: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
|
|
|
|
|
2018-05-27 18:56:51 +03:00
|
|
|
#include <stddef.h>
|
2018-10-27 01:08:58 +03:00
|
|
|
#include <stdint.h>
|
2018-10-29 22:50:29 +03:00
|
|
|
#include <stdbool.h>
|
2018-10-27 01:08:58 +03:00
|
|
|
|
|
|
|
#if defined _MSC_VER && _MSC_VER < 1800
|
|
|
|
/* Work around lack of inttypes.h in older MSVC */
|
2018-11-22 10:05:58 +03:00
|
|
|
#define PRIx32 "x"
|
2018-10-27 01:08:58 +03:00
|
|
|
#define PRIu64 "I64u"
|
|
|
|
#define SCNu64 "I64u"
|
|
|
|
#else
|
|
|
|
#include <inttypes.h>
|
|
|
|
#endif
|
2018-05-27 18:56:51 +03:00
|
|
|
|
2018-05-24 10:59:01 +03:00
|
|
|
typedef struct conf_tag Conf;
|
|
|
|
typedef struct terminal_tag Terminal;
|
|
|
|
|
|
|
|
typedef struct Filename Filename;
|
|
|
|
typedef struct FontSpec FontSpec;
|
|
|
|
|
|
|
|
typedef struct bufchain_tag bufchain;
|
|
|
|
|
|
|
|
typedef struct strbuf strbuf;
|
|
|
|
|
|
|
|
struct RSAKey;
|
|
|
|
|
2018-05-24 11:17:13 +03: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 10:25:19 +03:00
|
|
|
typedef struct BinarySource BinarySource;
|
2018-05-24 11:17:13 +03:00
|
|
|
|
2018-09-23 18:35:29 +03: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 21:10:23 +03:00
|
|
|
typedef struct SockAddr SockAddr;
|
2018-05-27 11:29:33 +03:00
|
|
|
|
2018-10-05 09:24:16 +03:00
|
|
|
typedef struct Socket Socket;
|
|
|
|
typedef struct Plug Plug;
|
2018-10-18 22:06:42 +03:00
|
|
|
typedef struct SocketPeerInfo SocketPeerInfo;
|
2018-05-27 11:29:33 +03:00
|
|
|
|
2018-09-11 18:23:38 +03:00
|
|
|
typedef struct Backend Backend;
|
2018-10-05 09:03:46 +03:00
|
|
|
typedef struct BackendVtable BackendVtable;
|
2018-09-11 18:23:38 +03:00
|
|
|
|
2018-09-11 17:02:59 +03: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 21:26:18 +03:00
|
|
|
typedef struct LogContext LogContext;
|
|
|
|
typedef struct LogPolicy LogPolicy;
|
|
|
|
typedef struct LogPolicyVtable LogPolicyVtable;
|
2018-09-11 17:02:59 +03: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 21:58:42 +03:00
|
|
|
typedef struct Seat Seat;
|
|
|
|
typedef struct SeatVtable SeatVtable;
|
|
|
|
|
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 20:44:04 +03:00
|
|
|
typedef struct TermWin TermWin;
|
|
|
|
typedef struct TermWinVtable TermWinVtable;
|
2018-09-12 11:10:51 +03: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 21:10:23 +03:00
|
|
|
typedef struct Ssh Ssh;
|
2018-09-11 18:23:38 +03:00
|
|
|
|
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-21 00:10:32 +03: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 17:03:47 +03:00
|
|
|
typedef struct Channel Channel;
|
2018-09-14 15:47:13 +03:00
|
|
|
typedef struct SshChannel SshChannel;
|
2018-09-30 09:16:38 +03: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 17:03:47 +03:00
|
|
|
|
2018-09-13 11:09:10 +03: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 19:04:39 +03:00
|
|
|
typedef struct PortFwdManager PortFwdManager;
|
|
|
|
typedef struct PortFwdRecord PortFwdRecord;
|
2018-09-17 14:14:00 +03:00
|
|
|
typedef struct ConnectionLayer ConnectionLayer;
|
2018-09-14 19:04:39 +03:00
|
|
|
|
2018-09-13 14:58:44 +03:00
|
|
|
typedef struct dlgparam dlgparam;
|
|
|
|
|
2018-09-14 10:45:42 +03:00
|
|
|
typedef struct settings_w settings_w;
|
|
|
|
typedef struct settings_r settings_r;
|
|
|
|
typedef struct settings_e settings_e;
|
|
|
|
|
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 11:35:52 +03:00
|
|
|
typedef struct SessionSpecial SessionSpecial;
|
|
|
|
|
2018-05-27 18:56:51 +03: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 11:00:11 +03:00
|
|
|
typedef struct logblank_t logblank_t;
|
|
|
|
|
2018-09-21 18:53:45 +03: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 20:28:16 +03:00
|
|
|
typedef struct PacketProtocolLayer PacketProtocolLayer;
|
2018-09-21 18:53:45 +03:00
|
|
|
|
2018-05-24 10:59:01 +03: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 16:55:10 +03:00
|
|
|
/* Return a pointer to the object of structure type 'type' whose field
|
|
|
|
* with name 'field' is pointed at by 'object'. */
|
2018-10-06 01:49:08 +03:00
|
|
|
#define container_of(object, type, field) \
|
2018-05-24 16:55:10 +03:00
|
|
|
TYPECHECK(object == &((type *)0)->field, \
|
|
|
|
((type *)(((char *)(object)) - offsetof(type, field))))
|
|
|
|
|
2018-05-24 10:59:01 +03:00
|
|
|
#endif /* PUTTY_DEFS_H */
|