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
|
2019-06-19 08:49:24 +03:00
|
|
|
/* Work around lack of inttypes.h and strtoumax in older MSVC */
|
2018-11-22 10:05:58 +03:00
|
|
|
#define PRIx32 "x"
|
2020-02-15 19:39:02 +03:00
|
|
|
#define PRIu32 "u"
|
2018-10-27 01:08:58 +03: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 22:08:37 +03:00
|
|
|
#define PRIdMAX "I64d"
|
|
|
|
#define PRIXMAX "I64X"
|
2018-10-27 01:08:58 +03:00
|
|
|
#define SCNu64 "I64u"
|
2020-01-26 13:59:07 +03:00
|
|
|
#define SIZEx "Ix"
|
|
|
|
#define SIZEu "Iu"
|
2019-06-19 08:49:24 +03:00
|
|
|
uintmax_t strtoumax(const char *nptr, char **endptr, int base);
|
2018-10-27 01:08:58 +03:00
|
|
|
#else
|
|
|
|
#include <inttypes.h>
|
2020-01-26 13:59:07 +03: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-27 01:08:58 +03:00
|
|
|
#endif
|
2018-05-27 18:56:51 +03:00
|
|
|
|
2020-01-26 17:49:31 +03: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 10:59:01 +03:00
|
|
|
typedef struct conf_tag Conf;
|
|
|
|
typedef struct terminal_tag Terminal;
|
2019-03-04 23:53:41 +03:00
|
|
|
typedef struct term_utf8_decode term_utf8_decode;
|
2018-05-24 10:59:01 +03:00
|
|
|
|
|
|
|
typedef struct Filename Filename;
|
|
|
|
typedef struct FontSpec FontSpec;
|
|
|
|
|
|
|
|
typedef struct bufchain_tag bufchain;
|
|
|
|
|
|
|
|
typedef struct strbuf strbuf;
|
2020-02-02 14:27:03 +03:00
|
|
|
typedef struct LoadedFile LoadedFile;
|
2018-05-24 10:59:01 +03:00
|
|
|
|
2019-01-04 09:51:44 +03:00
|
|
|
typedef struct RSAKey RSAKey;
|
2018-05-24 10:59:01 +03:00
|
|
|
|
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;
|
2019-02-20 09:52:54 +03:00
|
|
|
typedef struct stdio_sink stdio_sink;
|
|
|
|
typedef struct bufchain_sink bufchain_sink;
|
|
|
|
typedef struct handle_sink handle_sink;
|
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
|
|
|
|
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 16:53:41 +03: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 21:29:13 +03: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-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
|
|
|
|
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-23 01:42:41 +03:00
|
|
|
typedef struct prng prng;
|
2019-01-04 09:51:44 +03: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 21:06:08 +03:00
|
|
|
typedef struct ssh_cipheralg ssh_cipheralg;
|
|
|
|
typedef struct ssh_cipher ssh_cipher;
|
2019-01-04 09:51:44 +03:00
|
|
|
typedef struct ssh2_ciphers ssh2_ciphers;
|
|
|
|
typedef struct dh_ctx dh_ctx;
|
|
|
|
typedef struct ecdh_key ecdh_key;
|
|
|
|
|
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;
|
|
|
|
|
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 09:56:40 +03:00
|
|
|
typedef struct StripCtrlChars StripCtrlChars;
|
|
|
|
|
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-12-01 13:33:08 +03:00
|
|
|
#if defined __GNUC__ || defined __clang__
|
|
|
|
#define NORETURN __attribute__((__noreturn__))
|
|
|
|
#else
|
|
|
|
#define NORETURN
|
|
|
|
#endif
|
|
|
|
|
2019-01-04 02:28:53 +03:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Platform-specific definitions.
|
|
|
|
*
|
|
|
|
* Most of these live in the per-platform header files, of which
|
|
|
|
* puttyps.h selects the appropriate one. But some of the sources
|
|
|
|
* (particularly standalone test applications) would prefer not to
|
|
|
|
* have to include a per-platform header at all, because that makes it
|
|
|
|
* more portable to platforms not supported by the code base as a
|
|
|
|
* whole (for example, compiling purely computational parts of the
|
|
|
|
* code for specialist platforms for test and analysis purposes). So
|
|
|
|
* any definition that has to affect even _those_ modules will have to
|
|
|
|
* go here, with the key constraint being that this code has to come
|
|
|
|
* to _some_ decision even if the compilation platform is not a
|
|
|
|
* recognised one at all.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Purely computational code uses smemclr(), so we have to make the
|
|
|
|
* decision here about whether that's provided by utils.c or by a
|
|
|
|
* platform implementation. We define PLATFORM_HAS_SMEMCLR to suppress
|
|
|
|
* utils.c's definition. */
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
/* Windows provides the API function 'SecureZeroMemory', which we use
|
|
|
|
* unless the user has told us not to by defining NO_SECUREZEROMEMORY. */
|
|
|
|
#ifndef NO_SECUREZEROMEMORY
|
|
|
|
#define PLATFORM_HAS_SMEMCLR
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2018-05-24 10:59:01 +03:00
|
|
|
#endif /* PUTTY_DEFS_H */
|