2006-04-23 22:26:03 +04:00
|
|
|
/*
|
|
|
|
* SSH port forwarding.
|
|
|
|
*/
|
|
|
|
|
2018-05-31 00:36:20 +03:00
|
|
|
#include <assert.h>
|
2001-08-09 00:53:27 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "putty.h"
|
|
|
|
#include "ssh.h"
|
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
|
|
|
#include "sshchan.h"
|
2001-08-09 00:53:27 +04:00
|
|
|
|
2018-05-31 00:36:20 +03:00
|
|
|
/*
|
|
|
|
* Enumeration of values that live in the 'socks_state' field of
|
|
|
|
* struct PortForwarding.
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
SOCKS_NONE, /* direct connection (no SOCKS, or SOCKS already done) */
|
|
|
|
SOCKS_INITIAL, /* don't know if we're SOCKS 4 or 5 yet */
|
|
|
|
SOCKS_4, /* expect a SOCKS 4 (or 4A) connection message */
|
|
|
|
SOCKS_5_INITIAL, /* expect a SOCKS 5 preliminary message */
|
|
|
|
SOCKS_5_CONNECT /* expect a SOCKS 5 connection message */
|
|
|
|
} SocksState;
|
|
|
|
|
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 PortForwarding {
|
2018-09-17 14:14:00 +03:00
|
|
|
SshChannel *c; /* channel structure held by SSH connection layer */
|
|
|
|
ConnectionLayer *cl; /* the connection layer itself */
|
2018-09-11 17:33:10 +03:00
|
|
|
/* Note that ssh need not be filled in if c is non-NULL */
|
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
|
|
|
Socket *s;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
bool input_wanted;
|
|
|
|
bool ready;
|
2018-05-31 00:36:20 +03:00
|
|
|
SocksState socks_state;
|
2003-04-05 15:45:21 +04:00
|
|
|
/*
|
|
|
|
* `hostname' and `port' are the real hostname and port, once
|
2013-07-11 21:23:56 +04:00
|
|
|
* we know what we're connecting to.
|
2003-04-05 15:45:21 +04:00
|
|
|
*/
|
2013-07-11 21:23:56 +04:00
|
|
|
char *hostname;
|
2003-04-05 15:45:21 +04:00
|
|
|
int port;
|
2013-07-11 21:23:56 +04:00
|
|
|
/*
|
2018-05-31 00:36:20 +03:00
|
|
|
* `socksbuf' is the buffer we use to accumulate the initial SOCKS
|
|
|
|
* segment of the incoming data, plus anything after that that we
|
|
|
|
* receive before we're ready to send data to the SSH server.
|
2013-07-11 21:23:56 +04:00
|
|
|
*/
|
2018-05-31 00:36:20 +03:00
|
|
|
strbuf *socksbuf;
|
|
|
|
size_t socksbuf_consumed;
|
2018-05-27 11:29:33 +03:00
|
|
|
|
2018-10-05 09:24:16 +03:00
|
|
|
Plug plug;
|
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
|
|
|
Channel chan;
|
|
|
|
} PortForwarding;
|
2001-08-09 00:53:27 +04:00
|
|
|
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
struct PortListener {
|
2018-09-17 14:14:00 +03:00
|
|
|
ConnectionLayer *cl;
|
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
|
|
|
Socket *s;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
bool is_dynamic;
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
/*
|
|
|
|
* `hostname' and `port' are the real hostname and port, for
|
|
|
|
* ordinary forwardings.
|
|
|
|
*/
|
|
|
|
char *hostname;
|
|
|
|
int port;
|
2018-05-27 11:29:33 +03:00
|
|
|
|
2018-10-05 09:24:16 +03:00
|
|
|
Plug plug;
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct PortForwarding *new_portfwd_state(void)
|
2013-07-11 21:23:56 +04:00
|
|
|
{
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
struct PortForwarding *pf = snew(struct PortForwarding);
|
|
|
|
pf->hostname = NULL;
|
|
|
|
pf->socksbuf = NULL;
|
|
|
|
return pf;
|
2013-07-11 21:23:56 +04:00
|
|
|
}
|
|
|
|
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
static void free_portfwd_state(struct PortForwarding *pf)
|
2013-07-11 21:23:56 +04:00
|
|
|
{
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
if (!pf)
|
2013-07-11 21:23:56 +04:00
|
|
|
return;
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
sfree(pf->hostname);
|
2018-05-31 00:36:20 +03:00
|
|
|
if (pf->socksbuf)
|
|
|
|
strbuf_free(pf->socksbuf);
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
sfree(pf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct PortListener *new_portlistener_state(void)
|
|
|
|
{
|
|
|
|
struct PortListener *pl = snew(struct PortListener);
|
|
|
|
pl->hostname = NULL;
|
|
|
|
return pl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_portlistener_state(struct PortListener *pl)
|
|
|
|
{
|
|
|
|
if (!pl)
|
|
|
|
return;
|
|
|
|
sfree(pl->hostname);
|
|
|
|
sfree(pl);
|
2013-07-11 21:23:56 +04: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
|
|
|
static void pfd_log(Plug *plug, int type, SockAddr *addr, int port,
|
2019-09-08 22:29:00 +03:00
|
|
|
const char *error_msg, int error_code)
|
2005-01-16 17:29:34 +03:00
|
|
|
{
|
|
|
|
/* we have to dump these since we have no interface to logging.c */
|
|
|
|
}
|
|
|
|
|
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
|
|
|
static void pfl_log(Plug *plug, int type, SockAddr *addr, int port,
|
2019-09-08 22:29:00 +03:00
|
|
|
const char *error_msg, int error_code)
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
{
|
|
|
|
/* we have to dump these since we have no interface to logging.c */
|
|
|
|
}
|
|
|
|
|
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
|
|
|
static void pfd_close(struct PortForwarding *pf);
|
|
|
|
|
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
|
|
|
static void pfd_closing(Plug *plug, const char *error_msg, int error_code,
|
2019-09-08 22:29:00 +03:00
|
|
|
bool calling_back)
|
2001-08-09 00:53:27 +04:00
|
|
|
{
|
2018-10-06 01:49:08 +03:00
|
|
|
struct PortForwarding *pf =
|
|
|
|
container_of(plug, struct PortForwarding, plug);
|
2001-08-09 00:53:27 +04:00
|
|
|
|
2011-12-08 23:15:58 +04:00
|
|
|
if (error_msg) {
|
|
|
|
/*
|
|
|
|
* Socket error. Slam the connection instantly shut.
|
|
|
|
*/
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
if (pf->c) {
|
2018-10-13 12:30:03 +03:00
|
|
|
sshfwd_initiate_close(pf->c, error_msg);
|
2013-08-15 10:42:36 +04:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* We might not have an SSH channel, if a socket error
|
|
|
|
* occurred during SOCKS negotiation. If not, we must
|
2018-10-13 12:30:03 +03:00
|
|
|
* clean ourself up without sshfwd_initiate_close's call
|
2013-08-15 10:42:36 +04:00
|
|
|
* back to pfd_close.
|
|
|
|
*/
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
pfd_close(pf);
|
2013-08-15 10:42:36 +04:00
|
|
|
}
|
2011-12-08 23:15:58 +04:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Ordinary EOF received on socket. Send an EOF on the SSH
|
|
|
|
* channel.
|
|
|
|
*/
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
if (pf->c)
|
|
|
|
sshfwd_write_eof(pf->c);
|
2011-12-08 23:15:58 +04:00
|
|
|
}
|
2001-08-09 00:53:27 +04:00
|
|
|
}
|
|
|
|
|
2018-09-14 19:04:39 +03:00
|
|
|
static void pfl_terminate(struct PortListener *pl);
|
|
|
|
|
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
|
|
|
static void pfl_closing(Plug *plug, const char *error_msg, int error_code,
|
2019-09-08 22:29:00 +03:00
|
|
|
bool calling_back)
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
{
|
|
|
|
struct PortListener *pl = (struct PortListener *) plug;
|
|
|
|
pfl_terminate(pl);
|
|
|
|
}
|
|
|
|
|
2018-09-17 14:14:00 +03:00
|
|
|
static SshChannel *wrap_lportfwd_open(
|
|
|
|
ConnectionLayer *cl, const char *hostname, int port,
|
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
|
|
|
Socket *s, Channel *chan)
|
2015-05-18 15:57:45 +03:00
|
|
|
{
|
2018-10-18 22:06:42 +03:00
|
|
|
SocketPeerInfo *pi;
|
|
|
|
char *description;
|
2018-09-14 15:47:13 +03:00
|
|
|
SshChannel *toret;
|
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-10-18 22:06:42 +03:00
|
|
|
pi = sk_peer_info(s);
|
|
|
|
if (pi && pi->log_text) {
|
|
|
|
description = dupprintf("forwarding from %s", pi->log_text);
|
2015-05-18 15:57:45 +03:00
|
|
|
} else {
|
|
|
|
description = dupstr("forwarding");
|
|
|
|
}
|
2018-10-18 22:06:42 +03:00
|
|
|
toret = ssh_lportfwd_open(cl, hostname, port, description, pi, chan);
|
|
|
|
sk_free_peer_info(pi);
|
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
|
|
|
|
2015-05-18 15:57:45 +03:00
|
|
|
sfree(description);
|
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
|
|
|
return toret;
|
2015-05-18 15:57:45 +03:00
|
|
|
}
|
|
|
|
|
2018-05-31 00:36:20 +03:00
|
|
|
static char *ipv4_to_string(unsigned ipv4)
|
|
|
|
{
|
|
|
|
return dupprintf("%u.%u.%u.%u",
|
|
|
|
(ipv4 >> 24) & 0xFF, (ipv4 >> 16) & 0xFF,
|
|
|
|
(ipv4 >> 8) & 0xFF, (ipv4 ) & 0xFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *ipv6_to_string(ptrlen ipv6)
|
|
|
|
{
|
|
|
|
const unsigned char *addr = ipv6.ptr;
|
|
|
|
assert(ipv6.len == 16);
|
|
|
|
return dupprintf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
|
|
|
|
(unsigned)GET_16BIT_MSB_FIRST(addr + 0),
|
|
|
|
(unsigned)GET_16BIT_MSB_FIRST(addr + 2),
|
|
|
|
(unsigned)GET_16BIT_MSB_FIRST(addr + 4),
|
|
|
|
(unsigned)GET_16BIT_MSB_FIRST(addr + 6),
|
|
|
|
(unsigned)GET_16BIT_MSB_FIRST(addr + 8),
|
|
|
|
(unsigned)GET_16BIT_MSB_FIRST(addr + 10),
|
|
|
|
(unsigned)GET_16BIT_MSB_FIRST(addr + 12),
|
|
|
|
(unsigned)GET_16BIT_MSB_FIRST(addr + 14));
|
|
|
|
}
|
|
|
|
|
2019-02-06 23:42:44 +03:00
|
|
|
static void pfd_receive(Plug *plug, int urgent, const char *data, size_t len)
|
2001-08-09 00:53:27 +04:00
|
|
|
{
|
2018-10-06 01:49:08 +03:00
|
|
|
struct PortForwarding *pf =
|
|
|
|
container_of(plug, struct PortForwarding, plug);
|
2018-05-31 00:36:20 +03:00
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pf->socks_state != SOCKS_NONE) {
|
|
|
|
BinarySource src[1];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Store all the data we've got in socksbuf.
|
|
|
|
*/
|
|
|
|
put_data(pf->socksbuf, data, len);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the start of socksbuf to see if it's a valid and
|
|
|
|
* complete message in the SOCKS exchange.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (pf->socks_state == SOCKS_INITIAL) {
|
|
|
|
/* Preliminary: check the first byte of the data (which we
|
|
|
|
* _must_ have by now) to find out which SOCKS major
|
|
|
|
* version we're speaking. */
|
|
|
|
switch (pf->socksbuf->u[0]) {
|
|
|
|
case 4:
|
|
|
|
pf->socks_state = SOCKS_4;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
pf->socks_state = SOCKS_5_INITIAL;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pfd_close(pf); /* unrecognised version */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BinarySource_BARE_INIT(src, pf->socksbuf->u, pf->socksbuf->len);
|
|
|
|
get_data(src, pf->socksbuf_consumed);
|
|
|
|
|
|
|
|
while (pf->socks_state != SOCKS_NONE) {
|
|
|
|
unsigned socks_version, message_type, reserved_byte;
|
|
|
|
unsigned reply_code, port, ipv4, method;
|
|
|
|
ptrlen methods;
|
|
|
|
const char *socks4_hostname;
|
|
|
|
strbuf *output;
|
|
|
|
|
|
|
|
switch (pf->socks_state) {
|
|
|
|
case SOCKS_INITIAL:
|
|
|
|
case SOCKS_NONE:
|
2019-01-03 11:12:19 +03:00
|
|
|
unreachable("These case values cannot appear");
|
2018-05-31 00:36:20 +03:00
|
|
|
|
|
|
|
case SOCKS_4:
|
|
|
|
/* SOCKS 4/4A connect message */
|
|
|
|
socks_version = get_byte(src);
|
|
|
|
message_type = get_byte(src);
|
|
|
|
|
|
|
|
if (get_err(src) == BSE_OUT_OF_DATA)
|
|
|
|
return;
|
|
|
|
if (socks_version == 4 && message_type == 1) {
|
|
|
|
/* CONNECT message */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
bool name_based = false;
|
2018-05-31 00:36:20 +03:00
|
|
|
|
|
|
|
port = get_uint16(src);
|
|
|
|
ipv4 = get_uint32(src);
|
|
|
|
if (ipv4 > 0x00000000 && ipv4 < 0x00000100) {
|
|
|
|
/*
|
|
|
|
* Addresses in this range indicate the SOCKS 4A
|
|
|
|
* extension to specify a hostname, which comes
|
|
|
|
* after the username.
|
|
|
|
*/
|
2018-10-29 22:50:29 +03:00
|
|
|
name_based = true;
|
2018-05-31 00:36:20 +03:00
|
|
|
}
|
|
|
|
get_asciz(src); /* skip username */
|
|
|
|
socks4_hostname = name_based ? get_asciz(src) : NULL;
|
|
|
|
|
|
|
|
if (get_err(src) == BSE_OUT_OF_DATA)
|
|
|
|
return;
|
|
|
|
if (get_err(src))
|
|
|
|
goto socks4_reject;
|
|
|
|
|
|
|
|
pf->port = port;
|
|
|
|
if (name_based) {
|
|
|
|
pf->hostname = dupstr(socks4_hostname);
|
|
|
|
} else {
|
|
|
|
pf->hostname = ipv4_to_string(ipv4);
|
|
|
|
}
|
|
|
|
|
|
|
|
output = strbuf_new();
|
|
|
|
put_byte(output, 0); /* reply version */
|
|
|
|
put_byte(output, 90); /* SOCKS 4 'request granted' */
|
|
|
|
put_uint16(output, 0); /* null port field */
|
|
|
|
put_uint32(output, 0); /* null address field */
|
|
|
|
sk_write(pf->s, output->u, output->len);
|
|
|
|
strbuf_free(output);
|
|
|
|
|
|
|
|
pf->socks_state = SOCKS_NONE;
|
|
|
|
pf->socksbuf_consumed = src->pos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
socks4_reject:
|
|
|
|
output = strbuf_new();
|
|
|
|
put_byte(output, 0); /* reply version */
|
|
|
|
put_byte(output, 91); /* SOCKS 4 'request rejected' */
|
|
|
|
put_uint16(output, 0); /* null port field */
|
|
|
|
put_uint32(output, 0); /* null address field */
|
|
|
|
sk_write(pf->s, output->u, output->len);
|
|
|
|
strbuf_free(output);
|
|
|
|
pfd_close(pf);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SOCKS_5_INITIAL:
|
|
|
|
/* SOCKS 5 initial method list */
|
|
|
|
socks_version = get_byte(src);
|
|
|
|
methods = get_pstring(src);
|
|
|
|
|
|
|
|
method = 0xFF; /* means 'no usable method found' */
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < methods.len; i++) {
|
|
|
|
if (((const unsigned char *)methods.ptr)[i] == 0 ) {
|
|
|
|
method = 0; /* no auth */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (get_err(src) == BSE_OUT_OF_DATA)
|
|
|
|
return;
|
|
|
|
if (get_err(src))
|
|
|
|
method = 0xFF;
|
|
|
|
|
|
|
|
output = strbuf_new();
|
|
|
|
put_byte(output, 5); /* SOCKS version */
|
|
|
|
put_byte(output, method); /* selected auth method */
|
|
|
|
sk_write(pf->s, output->u, output->len);
|
|
|
|
strbuf_free(output);
|
|
|
|
|
|
|
|
if (method == 0xFF) {
|
|
|
|
pfd_close(pf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pf->socks_state = SOCKS_5_CONNECT;
|
|
|
|
pf->socksbuf_consumed = src->pos;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SOCKS_5_CONNECT:
|
|
|
|
/* SOCKS 5 connect message */
|
|
|
|
socks_version = get_byte(src);
|
|
|
|
message_type = get_byte(src);
|
|
|
|
reserved_byte = get_byte(src);
|
|
|
|
|
|
|
|
if (socks_version == 5 && message_type == 1 &&
|
|
|
|
reserved_byte == 0) {
|
|
|
|
|
|
|
|
reply_code = 0; /* success */
|
|
|
|
|
|
|
|
switch (get_byte(src)) {
|
|
|
|
case 1: /* IPv4 */
|
|
|
|
pf->hostname = ipv4_to_string(get_uint32(src));
|
|
|
|
break;
|
|
|
|
case 4: /* IPv6 */
|
|
|
|
pf->hostname = ipv6_to_string(get_data(src, 16));
|
|
|
|
break;
|
|
|
|
case 3: /* unresolved domain name */
|
|
|
|
pf->hostname = mkstr(get_pstring(src));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pf->hostname = NULL;
|
|
|
|
reply_code = 8; /* address type not supported */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
pf->port = get_uint16(src);
|
|
|
|
} else {
|
|
|
|
reply_code = 7; /* command not supported */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (get_err(src) == BSE_OUT_OF_DATA)
|
|
|
|
return;
|
|
|
|
if (get_err(src))
|
|
|
|
reply_code = 1; /* general server failure */
|
|
|
|
|
|
|
|
output = strbuf_new();
|
|
|
|
put_byte(output, 5); /* SOCKS version */
|
|
|
|
put_byte(output, reply_code);
|
|
|
|
put_byte(output, 0); /* reserved */
|
|
|
|
put_byte(output, 1); /* IPv4 address follows */
|
|
|
|
put_uint32(output, 0); /* bound IPv4 address (unused) */
|
|
|
|
put_uint16(output, 0); /* bound port number (unused) */
|
|
|
|
sk_write(pf->s, output->u, output->len);
|
|
|
|
strbuf_free(output);
|
|
|
|
|
|
|
|
if (reply_code != 0) {
|
|
|
|
pfd_close(pf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pf->socks_state = SOCKS_NONE;
|
|
|
|
pf->socksbuf_consumed = src->pos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-04-05 15:45:21 +04:00
|
|
|
|
2019-09-08 22:29:00 +03:00
|
|
|
/*
|
|
|
|
* We come here when we're ready to make an actual
|
|
|
|
* connection.
|
|
|
|
*/
|
2003-04-05 15:45:21 +04:00
|
|
|
|
2019-09-08 22:29:00 +03:00
|
|
|
/*
|
|
|
|
* Freeze the socket until the SSH server confirms the
|
|
|
|
* connection.
|
|
|
|
*/
|
|
|
|
sk_set_frozen(pf->s, 1);
|
2009-04-23 21:33:42 +04:00
|
|
|
|
2018-09-17 14:14:00 +03:00
|
|
|
pf->c = wrap_lportfwd_open(pf->cl, pf->hostname, pf->port, pf->s,
|
|
|
|
&pf->chan);
|
2001-08-25 21:09:23 +04:00
|
|
|
}
|
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
|
|
|
if (pf->ready)
|
|
|
|
sshfwd_write(pf->c, data, len);
|
2001-08-09 00:53:27 +04:00
|
|
|
}
|
|
|
|
|
2019-02-06 23:42:44 +03:00
|
|
|
static void pfd_sent(Plug *plug, size_t bufsize)
|
2001-08-25 21:09:23 +04:00
|
|
|
{
|
2018-10-06 01:49:08 +03:00
|
|
|
struct PortForwarding *pf =
|
|
|
|
container_of(plug, struct PortForwarding, plug);
|
2001-08-25 21:09:23 +04:00
|
|
|
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
if (pf->c)
|
2019-09-08 22:29:00 +03:00
|
|
|
sshfwd_unthrottle(pf->c, bufsize);
|
2001-08-25 21:09:23 +04:00
|
|
|
}
|
|
|
|
|
2018-10-05 09:03:46 +03:00
|
|
|
static const PlugVtable PortForwarding_plugvt = {
|
2018-05-27 11:29:33 +03:00
|
|
|
pfd_log,
|
|
|
|
pfd_closing,
|
|
|
|
pfd_receive,
|
|
|
|
pfd_sent,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
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
|
|
|
static void pfd_chan_free(Channel *chan);
|
|
|
|
static void pfd_open_confirmation(Channel *chan);
|
|
|
|
static void pfd_open_failure(Channel *chan, const char *errtext);
|
2019-02-06 23:42:44 +03:00
|
|
|
static size_t pfd_send(
|
|
|
|
Channel *chan, bool is_stderr, const void *data, size_t len);
|
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
|
|
|
static void pfd_send_eof(Channel *chan);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
static void pfd_set_input_wanted(Channel *chan, bool wanted);
|
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
|
|
|
static char *pfd_log_close_msg(Channel *chan);
|
|
|
|
|
|
|
|
static const struct ChannelVtable PortForwarding_channelvt = {
|
|
|
|
pfd_chan_free,
|
|
|
|
pfd_open_confirmation,
|
|
|
|
pfd_open_failure,
|
|
|
|
pfd_send,
|
|
|
|
pfd_send_eof,
|
|
|
|
pfd_set_input_wanted,
|
|
|
|
pfd_log_close_msg,
|
Allow channels not to close immediately after two EOFs.
Some kinds of channel, even after they've sent EOF in both directions,
still have something to do before they initiate the CLOSE mechanism
and wind up the channel completely. For example, a session channel
with a subprocess running inside it will want to be sure to send the
"exit-status" or "exit-signal" notification, even if that happens
after bidirectional EOF of the data channels.
Previously, the SSH-2 connection layer had the standard policy that
once EOF had been both sent and received, it would start the final
close procedure. There's a method chan_want_close() by which a Channel
could vary this policy in one direction, by indicating that it wanted
the close procedure to commence after EOF was sent in only one
direction. Its parameters are a pair of booleans saying whether EOF
has been sent, and whether it's been received.
Now chan_want_close can vary the policy in the other direction as
well: if it returns FALSE even when _both_ parameters are true, the
connection layer will honour that, and not send CHANNEL_CLOSE. If it
does that, the Channel is responsible for indicating when it _does_
want close later, by calling sshfwd_initiate_close.
2018-10-18 20:02:59 +03:00
|
|
|
chan_default_want_close,
|
2018-09-26 19:34:20 +03:00
|
|
|
chan_no_exit_status,
|
|
|
|
chan_no_exit_signal,
|
|
|
|
chan_no_exit_signal_numeric,
|
2018-10-20 23:48:49 +03:00
|
|
|
chan_no_run_shell,
|
|
|
|
chan_no_run_command,
|
|
|
|
chan_no_run_subsystem,
|
|
|
|
chan_no_enable_x11_forwarding,
|
|
|
|
chan_no_enable_agent_forwarding,
|
|
|
|
chan_no_allocate_pty,
|
|
|
|
chan_no_set_env,
|
|
|
|
chan_no_send_break,
|
|
|
|
chan_no_send_signal,
|
|
|
|
chan_no_change_window_size,
|
2018-09-26 20:02:33 +03:00
|
|
|
chan_no_request_response,
|
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-10-21 00:47:49 +03:00
|
|
|
Channel *portfwd_raw_new(ConnectionLayer *cl, Plug **plug)
|
2001-08-09 00:53:27 +04:00
|
|
|
{
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
struct PortForwarding *pf;
|
2001-08-09 00:53:27 +04:00
|
|
|
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
pf = new_portfwd_state();
|
2018-10-05 09:24:16 +03:00
|
|
|
pf->plug.vt = &PortForwarding_plugvt;
|
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
|
|
|
pf->chan.initial_fixed_window_size = 0;
|
|
|
|
pf->chan.vt = &PortForwarding_channelvt;
|
2018-10-29 22:50:29 +03:00
|
|
|
pf->input_wanted = true;
|
2001-08-09 00:53:27 +04:00
|
|
|
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
pf->c = NULL;
|
2001-08-09 00:53:27 +04:00
|
|
|
|
2018-10-21 00:47:49 +03:00
|
|
|
pf->cl = cl;
|
2018-10-29 22:50:29 +03:00
|
|
|
pf->input_wanted = true;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
pf->ready = false;
|
2018-10-21 00:47:49 +03:00
|
|
|
|
|
|
|
pf->socks_state = SOCKS_NONE;
|
|
|
|
pf->hostname = NULL;
|
|
|
|
pf->port = 0;
|
|
|
|
|
|
|
|
*plug = &pf->plug;
|
|
|
|
return &pf->chan;
|
|
|
|
}
|
|
|
|
|
|
|
|
void portfwd_raw_free(Channel *pfchan)
|
|
|
|
{
|
|
|
|
struct PortForwarding *pf;
|
|
|
|
assert(pfchan->vt == &PortForwarding_channelvt);
|
|
|
|
pf = container_of(pfchan, struct PortForwarding, chan);
|
|
|
|
free_portfwd_state(pf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void portfwd_raw_setup(Channel *pfchan, Socket *s, SshChannel *sc)
|
|
|
|
{
|
|
|
|
struct PortForwarding *pf;
|
|
|
|
assert(pfchan->vt == &PortForwarding_channelvt);
|
|
|
|
pf = container_of(pfchan, struct PortForwarding, chan);
|
|
|
|
|
|
|
|
pf->s = s;
|
|
|
|
pf->c = sc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
called when someone connects to the local port
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int pfl_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
|
|
|
|
{
|
|
|
|
struct PortListener *pl = container_of(p, struct PortListener, plug);
|
|
|
|
struct PortForwarding *pf;
|
|
|
|
Channel *chan;
|
|
|
|
Plug *plug;
|
|
|
|
Socket *s;
|
|
|
|
const char *err;
|
|
|
|
|
|
|
|
chan = portfwd_raw_new(pl->cl, &plug);
|
|
|
|
s = constructor(ctx, plug);
|
2003-01-05 16:04:04 +03:00
|
|
|
if ((err = sk_socket_error(s)) != NULL) {
|
2019-09-08 22:29:00 +03:00
|
|
|
portfwd_raw_free(chan);
|
|
|
|
return 1;
|
2001-08-09 00:53:27 +04:00
|
|
|
}
|
|
|
|
|
2018-10-21 00:47:49 +03:00
|
|
|
pf = container_of(chan, struct PortForwarding, chan);
|
2001-08-09 00:53:27 +04:00
|
|
|
|
2018-05-31 00:36:20 +03:00
|
|
|
if (pl->is_dynamic) {
|
2018-10-21 00:47:49 +03:00
|
|
|
pf->s = s;
|
2019-09-08 22:29:00 +03:00
|
|
|
pf->socks_state = SOCKS_INITIAL;
|
2018-05-31 00:36:20 +03:00
|
|
|
pf->socksbuf = strbuf_new();
|
|
|
|
pf->socksbuf_consumed = 0;
|
2019-09-08 22:29:00 +03:00
|
|
|
pf->port = 0; /* "hostname" buffer is so far empty */
|
|
|
|
sk_set_frozen(s, 0); /* we want to receive SOCKS _now_! */
|
2001-08-09 00:53:27 +04:00
|
|
|
} else {
|
2019-09-08 22:29:00 +03:00
|
|
|
pf->hostname = dupstr(pl->hostname);
|
|
|
|
pf->port = pl->port;
|
2018-10-21 00:47:49 +03:00
|
|
|
portfwd_raw_setup(
|
|
|
|
chan, s,
|
|
|
|
wrap_lportfwd_open(pl->cl, pf->hostname, pf->port, s, &pf->chan));
|
2001-08-09 00:53:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-10-05 09:03:46 +03:00
|
|
|
static const PlugVtable PortListener_plugvt = {
|
2018-05-27 11:29:33 +03:00
|
|
|
pfl_log,
|
|
|
|
pfl_closing,
|
|
|
|
NULL, /* recv */
|
|
|
|
NULL, /* send */
|
|
|
|
pfl_accepting
|
|
|
|
};
|
2001-08-09 00:53:27 +04:00
|
|
|
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
/*
|
|
|
|
* Add a new port-forwarding listener from srcaddr:port -> desthost:destport.
|
|
|
|
*
|
2018-09-14 19:04:39 +03:00
|
|
|
* desthost == NULL indicates dynamic SOCKS port forwarding.
|
|
|
|
*
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
* On success, returns NULL and fills in *pl_ret. On error, returns a
|
|
|
|
* dynamically allocated error message string.
|
2001-08-09 00:53:27 +04:00
|
|
|
*/
|
2018-10-21 00:46:24 +03:00
|
|
|
static char *pfl_listen(const char *desthost, int destport,
|
|
|
|
const char *srcaddr, int port,
|
|
|
|
ConnectionLayer *cl, Conf *conf,
|
2018-09-14 19:04:39 +03:00
|
|
|
struct PortListener **pl_ret, int address_family)
|
2001-08-09 00:53:27 +04:00
|
|
|
{
|
2003-05-04 18:18:18 +04:00
|
|
|
const char *err;
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
struct PortListener *pl;
|
2001-08-09 00:53:27 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Open socket.
|
|
|
|
*/
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
pl = *pl_ret = new_portlistener_state();
|
2018-10-05 09:24:16 +03:00
|
|
|
pl->plug.vt = &PortListener_plugvt;
|
2003-04-05 15:45:21 +04:00
|
|
|
if (desthost) {
|
2019-09-08 22:29:00 +03:00
|
|
|
pl->hostname = dupstr(desthost);
|
|
|
|
pl->port = destport;
|
|
|
|
pl->is_dynamic = false;
|
2003-04-05 15:45:21 +04:00
|
|
|
} else
|
2019-09-08 22:29:00 +03:00
|
|
|
pl->is_dynamic = true;
|
2018-09-17 14:14:00 +03:00
|
|
|
pl->cl = cl;
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
|
2018-10-05 09:24:16 +03:00
|
|
|
pl->s = new_listener(srcaddr, port, &pl->plug,
|
2018-10-29 22:57:31 +03:00
|
|
|
!conf_get_bool(conf, CONF_lport_acceptall),
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
conf, address_family);
|
|
|
|
if ((err = sk_socket_error(pl->s)) != NULL) {
|
|
|
|
char *err_ret = dupstr(err);
|
|
|
|
sk_close(pl->s);
|
2019-09-08 22:29:00 +03:00
|
|
|
free_portlistener_state(pl);
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
*pl_ret = NULL;
|
2019-09-08 22:29:00 +03:00
|
|
|
return err_ret;
|
2001-08-09 00:53:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
static char *pfd_log_close_msg(Channel *chan)
|
|
|
|
{
|
|
|
|
return dupstr("Forwarded port closed");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pfd_close(struct PortForwarding *pf)
|
2001-08-09 00:53:27 +04:00
|
|
|
{
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
if (!pf)
|
2019-09-08 22:29:00 +03:00
|
|
|
return;
|
2001-08-09 00:53:27 +04:00
|
|
|
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
sk_close(pf->s);
|
|
|
|
free_portfwd_state(pf);
|
2001-08-09 00:53:27 +04:00
|
|
|
}
|
|
|
|
|
2004-12-28 17:07:05 +03:00
|
|
|
/*
|
|
|
|
* Terminate a listener.
|
|
|
|
*/
|
2018-09-14 19:04:39 +03:00
|
|
|
static void pfl_terminate(struct PortListener *pl)
|
2004-12-28 17:07:05 +03:00
|
|
|
{
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
if (!pl)
|
2019-09-08 22:29:00 +03:00
|
|
|
return;
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
|
|
|
|
sk_close(pl->s);
|
|
|
|
free_portlistener_state(pl);
|
2004-12-28 17:07:05 +03:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
static void pfd_set_input_wanted(Channel *chan, bool wanted)
|
2001-08-25 21:09:23 +04:00
|
|
|
{
|
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
|
|
|
assert(chan->vt == &PortForwarding_channelvt);
|
2018-10-06 01:49:08 +03:00
|
|
|
PortForwarding *pf = container_of(chan, PortForwarding, chan);
|
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
|
|
|
pf->input_wanted = wanted;
|
|
|
|
sk_set_frozen(pf->s, !pf->input_wanted);
|
2001-08-25 21:09:23 +04:00
|
|
|
}
|
|
|
|
|
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
|
|
|
static void pfd_chan_free(Channel *chan)
|
2001-08-25 21:09:23 +04:00
|
|
|
{
|
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
|
|
|
assert(chan->vt == &PortForwarding_channelvt);
|
2018-10-06 01:49:08 +03:00
|
|
|
PortForwarding *pf = container_of(chan, PortForwarding, chan);
|
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
|
|
|
pfd_close(pf);
|
2001-08-25 21:09:23 +04:00
|
|
|
}
|
|
|
|
|
2001-08-09 00:53:27 +04:00
|
|
|
/*
|
|
|
|
* Called to send data down the raw connection.
|
|
|
|
*/
|
2019-02-06 23:42:44 +03:00
|
|
|
static size_t pfd_send(
|
|
|
|
Channel *chan, bool is_stderr, const void *data, size_t len)
|
2001-08-09 00:53:27 +04:00
|
|
|
{
|
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
|
|
|
assert(chan->vt == &PortForwarding_channelvt);
|
2018-10-06 01:49:08 +03:00
|
|
|
PortForwarding *pf = container_of(chan, PortForwarding, chan);
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
return sk_write(pf->s, data, len);
|
2001-08-09 00:53:27 +04:00
|
|
|
}
|
|
|
|
|
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
|
|
|
static void pfd_send_eof(Channel *chan)
|
2011-09-13 15:44:03 +04:00
|
|
|
{
|
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
|
|
|
assert(chan->vt == &PortForwarding_channelvt);
|
2018-10-06 01:49:08 +03:00
|
|
|
PortForwarding *pf = container_of(chan, PortForwarding, chan);
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
sk_write_eof(pf->s);
|
2011-09-13 15:44:03 +04:00
|
|
|
}
|
2001-08-09 00:53:27 +04:00
|
|
|
|
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
|
|
|
static void pfd_open_confirmation(Channel *chan)
|
2001-08-09 00:53:27 +04:00
|
|
|
{
|
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
|
|
|
assert(chan->vt == &PortForwarding_channelvt);
|
2018-10-06 01:49:08 +03:00
|
|
|
PortForwarding *pf = container_of(chan, PortForwarding, chan);
|
2001-08-09 00:53:27 +04:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
pf->ready = true;
|
Refactor ssh.c's APIs to x11fwd.c and portfwd.c.
The most important change is that, where previously ssh.c held the
Socket pointer for each X11 and port forwarding, and the support
modules would find their internal state structure by calling
sk_get_private_ptr on that Socket, it's now the other way round. ssh.c
now directly holds the internal state structure pointer for each
forwarding, and when the support module needs the Socket it looks it
up in a field of that. This will come in handy when I decouple socket
creation from logical forwarding setup, so that X forwardings can
delay actually opening a connection to an X server until they look at
the authentication data and see which server it has to be.
However, while I'm here, I've also taken the opportunity to clean up a
few other points, notably error message handling, and also the fact
that the same kind of state structure was used for both
connection-type and listening-type port forwardings. Now there are
separate PortForwarding and PortListener structure types, which seems
far more sensible.
[originally from svn r10074]
2013-11-17 18:04:41 +04:00
|
|
|
sk_set_frozen(pf->s, 0);
|
|
|
|
sk_write(pf->s, NULL, 0);
|
2018-05-31 00:36:20 +03:00
|
|
|
if (pf->socksbuf) {
|
2019-09-08 22:29:00 +03:00
|
|
|
sshfwd_write(pf->c, pf->socksbuf->u + pf->socksbuf_consumed,
|
2018-05-31 00:36:20 +03:00
|
|
|
pf->socksbuf->len - pf->socksbuf_consumed);
|
|
|
|
strbuf_free(pf->socksbuf);
|
|
|
|
pf->socksbuf = NULL;
|
2003-04-05 15:45:21 +04:00
|
|
|
}
|
2001-08-09 00:53:27 +04:00
|
|
|
}
|
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
|
|
|
|
|
|
|
static void pfd_open_failure(Channel *chan, const char *errtext)
|
|
|
|
{
|
|
|
|
assert(chan->vt == &PortForwarding_channelvt);
|
2018-10-06 01:49:08 +03:00
|
|
|
PortForwarding *pf = container_of(chan, PortForwarding, chan);
|
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
|
|
|
|
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
|
|
|
logeventf(pf->cl->logctx,
|
2018-10-20 23:52:45 +03:00
|
|
|
"Forwarded connection refused by remote%s%s",
|
2018-09-14 19:04:39 +03:00
|
|
|
errtext ? ": " : "", errtext ? errtext : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Code to manage the complete set of currently active port
|
|
|
|
* forwardings, and update it from Conf.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct PortFwdRecord {
|
|
|
|
enum { DESTROY, KEEP, CREATE } status;
|
|
|
|
int type;
|
|
|
|
unsigned sport, dport;
|
|
|
|
char *saddr, *daddr;
|
|
|
|
char *sserv, *dserv;
|
|
|
|
struct ssh_rportfwd *remote;
|
|
|
|
int addressfamily;
|
|
|
|
struct PortListener *local;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int pfr_cmp(void *av, void *bv)
|
|
|
|
{
|
|
|
|
PortFwdRecord *a = (PortFwdRecord *) av;
|
|
|
|
PortFwdRecord *b = (PortFwdRecord *) bv;
|
|
|
|
int i;
|
|
|
|
if (a->type > b->type)
|
|
|
|
return +1;
|
|
|
|
if (a->type < b->type)
|
|
|
|
return -1;
|
|
|
|
if (a->addressfamily > b->addressfamily)
|
|
|
|
return +1;
|
|
|
|
if (a->addressfamily < b->addressfamily)
|
|
|
|
return -1;
|
|
|
|
if ( (i = nullstrcmp(a->saddr, b->saddr)) != 0)
|
|
|
|
return i < 0 ? -1 : +1;
|
|
|
|
if (a->sport > b->sport)
|
|
|
|
return +1;
|
|
|
|
if (a->sport < b->sport)
|
|
|
|
return -1;
|
|
|
|
if (a->type != 'D') {
|
|
|
|
if ( (i = nullstrcmp(a->daddr, b->daddr)) != 0)
|
|
|
|
return i < 0 ? -1 : +1;
|
|
|
|
if (a->dport > b->dport)
|
|
|
|
return +1;
|
|
|
|
if (a->dport < b->dport)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void pfr_free(PortFwdRecord *pfr)
|
|
|
|
{
|
|
|
|
/* Dispose of any listening socket. */
|
|
|
|
if (pfr->local)
|
|
|
|
pfl_terminate(pfr->local);
|
|
|
|
|
|
|
|
sfree(pfr->saddr);
|
|
|
|
sfree(pfr->daddr);
|
|
|
|
sfree(pfr->sserv);
|
|
|
|
sfree(pfr->dserv);
|
|
|
|
sfree(pfr);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct PortFwdManager {
|
2018-09-17 14:14:00 +03:00
|
|
|
ConnectionLayer *cl;
|
2018-09-14 19:04:39 +03:00
|
|
|
Conf *conf;
|
|
|
|
tree234 *forwardings;
|
|
|
|
};
|
|
|
|
|
2018-09-17 14:14:00 +03:00
|
|
|
PortFwdManager *portfwdmgr_new(ConnectionLayer *cl)
|
2018-09-14 19:04:39 +03:00
|
|
|
{
|
|
|
|
PortFwdManager *mgr = snew(PortFwdManager);
|
|
|
|
|
2018-09-17 14:14:00 +03:00
|
|
|
mgr->cl = cl;
|
2018-09-14 19:04:39 +03:00
|
|
|
mgr->conf = NULL;
|
|
|
|
mgr->forwardings = newtree234(pfr_cmp);
|
|
|
|
|
|
|
|
return mgr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void portfwdmgr_close(PortFwdManager *mgr, PortFwdRecord *pfr)
|
|
|
|
{
|
|
|
|
PortFwdRecord *realpfr = del234(mgr->forwardings, pfr);
|
|
|
|
if (realpfr == pfr)
|
|
|
|
pfr_free(pfr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void portfwdmgr_close_all(PortFwdManager *mgr)
|
|
|
|
{
|
|
|
|
PortFwdRecord *pfr;
|
|
|
|
|
|
|
|
while ((pfr = delpos234(mgr->forwardings, 0)) != NULL)
|
|
|
|
pfr_free(pfr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void portfwdmgr_free(PortFwdManager *mgr)
|
|
|
|
{
|
|
|
|
portfwdmgr_close_all(mgr);
|
|
|
|
freetree234(mgr->forwardings);
|
|
|
|
if (mgr->conf)
|
|
|
|
conf_free(mgr->conf);
|
|
|
|
sfree(mgr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void portfwdmgr_config(PortFwdManager *mgr, Conf *conf)
|
|
|
|
{
|
|
|
|
PortFwdRecord *pfr;
|
|
|
|
int i;
|
|
|
|
char *key, *val;
|
|
|
|
|
|
|
|
if (mgr->conf)
|
|
|
|
conf_free(mgr->conf);
|
|
|
|
mgr->conf = conf_copy(conf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Go through the existing port forwardings and tag them
|
|
|
|
* with status==DESTROY. Any that we want to keep will be
|
|
|
|
* re-enabled (status==KEEP) as we go through the
|
|
|
|
* configuration and find out which bits are the same as
|
|
|
|
* they were before.
|
|
|
|
*/
|
|
|
|
for (i = 0; (pfr = index234(mgr->forwardings, i)) != NULL; i++)
|
|
|
|
pfr->status = DESTROY;
|
|
|
|
|
|
|
|
for (val = conf_get_str_strs(conf, CONF_portfwd, NULL, &key);
|
|
|
|
val != NULL;
|
|
|
|
val = conf_get_str_strs(conf, CONF_portfwd, key, &key)) {
|
|
|
|
char *kp, *kp2, *vp, *vp2;
|
|
|
|
char address_family, type;
|
|
|
|
int sport, dport, sserv, dserv;
|
|
|
|
char *sports, *dports, *saddr, *host;
|
|
|
|
|
|
|
|
kp = key;
|
|
|
|
|
|
|
|
address_family = 'A';
|
|
|
|
type = 'L';
|
|
|
|
if (*kp == 'A' || *kp == '4' || *kp == '6')
|
|
|
|
address_family = *kp++;
|
|
|
|
if (*kp == 'L' || *kp == 'R')
|
|
|
|
type = *kp++;
|
|
|
|
|
|
|
|
if ((kp2 = host_strchr(kp, ':')) != NULL) {
|
|
|
|
/*
|
|
|
|
* There's a colon in the middle of the source port
|
|
|
|
* string, which means that the part before it is
|
|
|
|
* actually a source address.
|
|
|
|
*/
|
|
|
|
char *saddr_tmp = dupprintf("%.*s", (int)(kp2 - kp), kp);
|
|
|
|
saddr = host_strduptrim(saddr_tmp);
|
|
|
|
sfree(saddr_tmp);
|
|
|
|
sports = kp2+1;
|
|
|
|
} else {
|
|
|
|
saddr = NULL;
|
|
|
|
sports = kp;
|
|
|
|
}
|
|
|
|
sport = atoi(sports);
|
|
|
|
sserv = 0;
|
|
|
|
if (sport == 0) {
|
|
|
|
sserv = 1;
|
|
|
|
sport = net_service_lookup(sports);
|
|
|
|
if (!sport) {
|
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
|
|
|
logeventf(mgr->cl->logctx, "Service lookup failed for source"
|
2018-09-14 19:04:39 +03:00
|
|
|
" port \"%s\"", sports);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == 'L' && !strcmp(val, "D")) {
|
|
|
|
/* dynamic forwarding */
|
|
|
|
host = NULL;
|
|
|
|
dports = NULL;
|
|
|
|
dport = -1;
|
|
|
|
dserv = 0;
|
|
|
|
type = 'D';
|
|
|
|
} else {
|
|
|
|
/* ordinary forwarding */
|
|
|
|
vp = val;
|
|
|
|
vp2 = vp + host_strcspn(vp, ":");
|
|
|
|
host = dupprintf("%.*s", (int)(vp2 - vp), vp);
|
|
|
|
if (*vp2)
|
|
|
|
vp2++;
|
|
|
|
dports = vp2;
|
|
|
|
dport = atoi(dports);
|
|
|
|
dserv = 0;
|
|
|
|
if (dport == 0) {
|
|
|
|
dserv = 1;
|
|
|
|
dport = net_service_lookup(dports);
|
|
|
|
if (!dport) {
|
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
|
|
|
logeventf(mgr->cl->logctx,
|
2018-09-14 19:04:39 +03:00
|
|
|
"Service lookup failed for destination"
|
|
|
|
" port \"%s\"", dports);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sport && dport) {
|
|
|
|
/* Set up a description of the source port. */
|
|
|
|
pfr = snew(PortFwdRecord);
|
|
|
|
pfr->type = type;
|
|
|
|
pfr->saddr = saddr;
|
|
|
|
pfr->sserv = sserv ? dupstr(sports) : NULL;
|
|
|
|
pfr->sport = sport;
|
|
|
|
pfr->daddr = host;
|
|
|
|
pfr->dserv = dserv ? dupstr(dports) : NULL;
|
|
|
|
pfr->dport = dport;
|
|
|
|
pfr->local = NULL;
|
|
|
|
pfr->remote = NULL;
|
|
|
|
pfr->addressfamily = (address_family == '4' ? ADDRTYPE_IPV4 :
|
|
|
|
address_family == '6' ? ADDRTYPE_IPV6 :
|
|
|
|
ADDRTYPE_UNSPEC);
|
|
|
|
|
|
|
|
PortFwdRecord *existing = add234(mgr->forwardings, pfr);
|
|
|
|
if (existing != pfr) {
|
|
|
|
if (existing->status == DESTROY) {
|
|
|
|
/*
|
|
|
|
* We already have a port forwarding up and running
|
|
|
|
* with precisely these parameters. Hence, no need
|
|
|
|
* to do anything; simply re-tag the existing one
|
|
|
|
* as KEEP.
|
|
|
|
*/
|
|
|
|
existing->status = KEEP;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Anything else indicates that there was a duplicate
|
|
|
|
* in our input, which we'll silently ignore.
|
|
|
|
*/
|
|
|
|
pfr_free(pfr);
|
|
|
|
} else {
|
|
|
|
pfr->status = CREATE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sfree(saddr);
|
|
|
|
sfree(host);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now go through and destroy any port forwardings which were
|
|
|
|
* not re-enabled.
|
|
|
|
*/
|
|
|
|
for (i = 0; (pfr = index234(mgr->forwardings, i)) != NULL; i++) {
|
|
|
|
if (pfr->status == DESTROY) {
|
|
|
|
char *message;
|
|
|
|
|
|
|
|
message = dupprintf("%s port forwarding from %s%s%d",
|
|
|
|
pfr->type == 'L' ? "local" :
|
|
|
|
pfr->type == 'R' ? "remote" : "dynamic",
|
|
|
|
pfr->saddr ? pfr->saddr : "",
|
|
|
|
pfr->saddr ? ":" : "",
|
|
|
|
pfr->sport);
|
|
|
|
|
|
|
|
if (pfr->type != 'D') {
|
|
|
|
char *msg2 = dupprintf("%s to %s:%d", message,
|
|
|
|
pfr->daddr, pfr->dport);
|
|
|
|
sfree(message);
|
|
|
|
message = msg2;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
logeventf(mgr->cl->logctx, "Cancelling %s", message);
|
2018-09-14 19:04:39 +03:00
|
|
|
sfree(message);
|
|
|
|
|
|
|
|
/* pfr->remote or pfr->local may be NULL if setting up a
|
|
|
|
* forwarding failed. */
|
|
|
|
if (pfr->remote) {
|
|
|
|
/*
|
|
|
|
* Cancel the port forwarding at the server
|
|
|
|
* end.
|
|
|
|
*
|
|
|
|
* Actually closing the listening port on the server
|
|
|
|
* side may fail - because in SSH-1 there's no message
|
|
|
|
* in the protocol to request it!
|
|
|
|
*
|
|
|
|
* Instead, we simply remove the record of the
|
|
|
|
* forwarding from our local end, so that any
|
|
|
|
* connections the server tries to make on it are
|
|
|
|
* rejected.
|
|
|
|
*/
|
2018-09-17 14:14:00 +03:00
|
|
|
ssh_rportfwd_remove(mgr->cl, pfr->remote);
|
2019-03-25 23:49:04 +03:00
|
|
|
pfr->remote = NULL;
|
2018-09-14 19:04:39 +03:00
|
|
|
} else if (pfr->local) {
|
|
|
|
pfl_terminate(pfr->local);
|
2019-03-25 23:49:04 +03:00
|
|
|
pfr->local = NULL;
|
2018-09-14 19:04:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
delpos234(mgr->forwardings, i);
|
|
|
|
pfr_free(pfr);
|
|
|
|
i--; /* so we don't skip one in the list */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* And finally, set up any new port forwardings (status==CREATE).
|
|
|
|
*/
|
|
|
|
for (i = 0; (pfr = index234(mgr->forwardings, i)) != NULL; i++) {
|
|
|
|
if (pfr->status == CREATE) {
|
|
|
|
char *sportdesc, *dportdesc;
|
|
|
|
sportdesc = dupprintf("%s%s%s%s%d%s",
|
|
|
|
pfr->saddr ? pfr->saddr : "",
|
|
|
|
pfr->saddr ? ":" : "",
|
|
|
|
pfr->sserv ? pfr->sserv : "",
|
|
|
|
pfr->sserv ? "(" : "",
|
|
|
|
pfr->sport,
|
|
|
|
pfr->sserv ? ")" : "");
|
|
|
|
if (pfr->type == 'D') {
|
|
|
|
dportdesc = NULL;
|
|
|
|
} else {
|
|
|
|
dportdesc = dupprintf("%s:%s%s%d%s",
|
|
|
|
pfr->daddr,
|
|
|
|
pfr->dserv ? pfr->dserv : "",
|
|
|
|
pfr->dserv ? "(" : "",
|
|
|
|
pfr->dport,
|
|
|
|
pfr->dserv ? ")" : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pfr->type == 'L') {
|
|
|
|
char *err = pfl_listen(pfr->daddr, pfr->dport,
|
|
|
|
pfr->saddr, pfr->sport,
|
2018-09-17 14:14:00 +03:00
|
|
|
mgr->cl, conf, &pfr->local,
|
2018-09-14 19:04:39 +03:00
|
|
|
pfr->addressfamily);
|
|
|
|
|
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
|
|
|
logeventf(mgr->cl->logctx,
|
2018-09-14 19:04:39 +03:00
|
|
|
"Local %sport %s forwarding to %s%s%s",
|
|
|
|
pfr->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
|
|
|
|
pfr->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
|
|
|
|
sportdesc, dportdesc,
|
|
|
|
err ? " failed: " : "", err ? err : "");
|
|
|
|
if (err)
|
|
|
|
sfree(err);
|
|
|
|
} else if (pfr->type == 'D') {
|
|
|
|
char *err = pfl_listen(NULL, -1, pfr->saddr, pfr->sport,
|
2018-09-17 14:14:00 +03:00
|
|
|
mgr->cl, conf, &pfr->local,
|
2018-09-14 19:04:39 +03:00
|
|
|
pfr->addressfamily);
|
|
|
|
|
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
|
|
|
logeventf(mgr->cl->logctx,
|
2018-09-14 19:04:39 +03:00
|
|
|
"Local %sport %s SOCKS dynamic forwarding%s%s",
|
|
|
|
pfr->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
|
|
|
|
pfr->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
|
|
|
|
sportdesc,
|
|
|
|
err ? " failed: " : "", err ? err : "");
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
sfree(err);
|
|
|
|
} else {
|
|
|
|
const char *shost;
|
|
|
|
|
|
|
|
if (pfr->saddr) {
|
|
|
|
shost = pfr->saddr;
|
2018-10-29 22:57:31 +03:00
|
|
|
} else if (conf_get_bool(conf, CONF_rport_acceptall)) {
|
2018-09-14 19:04:39 +03:00
|
|
|
shost = "";
|
|
|
|
} else {
|
|
|
|
shost = "localhost";
|
|
|
|
}
|
|
|
|
|
|
|
|
pfr->remote = ssh_rportfwd_alloc(
|
2018-09-17 14:14:00 +03:00
|
|
|
mgr->cl, shost, pfr->sport, pfr->daddr, pfr->dport,
|
2018-09-14 19:04:39 +03:00
|
|
|
pfr->addressfamily, sportdesc, pfr, NULL);
|
|
|
|
|
|
|
|
if (!pfr->remote) {
|
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
|
|
|
logeventf(mgr->cl->logctx,
|
2018-09-14 19:04:39 +03:00
|
|
|
"Duplicate remote port forwarding to %s:%d",
|
|
|
|
pfr->daddr, pfr->dport);
|
|
|
|
pfr_free(pfr);
|
|
|
|
} else {
|
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
|
|
|
logeventf(mgr->cl->logctx, "Requesting remote port %s"
|
2018-09-14 19:04:39 +03:00
|
|
|
" forward to %s", sportdesc, dportdesc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sfree(sportdesc);
|
|
|
|
sfree(dportdesc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
bool portfwdmgr_listen(PortFwdManager *mgr, const char *host, int port,
|
|
|
|
const char *keyhost, int keyport, Conf *conf)
|
Add an actual SSH server program.
This server is NOT SECURE! If anyone is reading this commit message,
DO NOT DEPLOY IT IN A HOSTILE-FACING ENVIRONMENT! Its purpose is to
speak the server end of everything PuTTY speaks on the client side, so
that I can test that I haven't broken PuTTY when I reorganise its
code, even things like RSA key exchange or chained auth methods which
it's hard to find a server that speaks at all.
(For this reason, it's declared with [UT] in the Recipe file, so that
it falls into the same category as programs like testbn, which won't
be installed by 'make install'.)
Working title is 'Uppity', partly for 'Universal PuTTY Protocol
Interaction Test Yoke', but mostly because it looks quite like the
word 'PuTTY' with part of it reversed. (Apparently 'test yoke' is a
very rarely used term meaning something not altogether unlike 'test
harness', which is a bit of a stretch, but it'll do.)
It doesn't actually _support_ everything I want yet. At the moment,
it's a proof of concept only. But it has most of the machinery
present, and the parts it's missing - such as chained auth methods -
should be easy enough to add because I've built in the required
flexibility, in the form of an AuthPolicy object which can request
them if it wants to. However, the current AuthPolicy object is
entirely trivial, and will let in any user with the password "weasel".
(Another way in which this is not a production-ready server is that it
also has no interaction with the OS's authentication system. In
particular, it will not only let in any user with the same password,
but it won't even change uid - it will open shells and forwardings
under whatever user id you started it up as.)
Currently, the program can only speak the SSH protocol on its standard
I/O channels (using the new FdSocket facility), so if you want it to
listen on a network port, you'll have to run it from some kind of
separate listening program similar to inetd. For my own tests, I'm not
even doing that: I'm just having PuTTY spawn it as a local proxy
process, which also conveniently eliminates the risk of anyone hostile
connecting to it.
The bulk of the actual code reorganisation is already done by previous
commits, so this change is _mostly_ just dropping in a new set of
server-specific source files alongside the client-specific ones I
created recently. The remaining changes in the shared SSH code are
numerous, but all minor:
- a few extra parameters to BPP and PPL constructors (e.g. 'are you
in server mode?'), and pass both sets of SSH-1 protocol flags from
the login to the connection layer
- in server mode, unconditionally send our version string _before_
waiting for the remote one
- a new hook in the SSH-1 BPP to handle enabling compression in
server mode, where the message exchange works the other way round
- new code in the SSH-2 BPP to do _deferred_ compression the other
way round (the non-deferred version is still nicely symmetric)
- in the SSH-2 transport layer, some adjustments to do key derivation
either way round (swapping round the identifying letters in the
various hash preimages, and making sure to list the KEXINITs in the
right order)
- also in the SSH-2 transport layer, an if statement that controls
whether we send SERVICE_REQUEST and wait for SERVICE_ACCEPT, or
vice versa
- new ConnectionLayer methods for opening outgoing channels for X and
agent forwardings
- new functions in portfwd.c to establish listening sockets suitable
for remote-to-local port forwarding (i.e. not under the direction
of a Conf the way it's done on the client side).
2018-10-21 00:09:54 +03:00
|
|
|
{
|
|
|
|
PortFwdRecord *pfr;
|
|
|
|
|
|
|
|
pfr = snew(PortFwdRecord);
|
|
|
|
pfr->type = 'L';
|
|
|
|
pfr->saddr = host ? dupstr(host) : NULL;
|
|
|
|
pfr->daddr = keyhost ? dupstr(keyhost) : NULL;
|
|
|
|
pfr->sserv = pfr->dserv = NULL;
|
|
|
|
pfr->sport = port;
|
|
|
|
pfr->dport = keyport;
|
|
|
|
pfr->local = NULL;
|
|
|
|
pfr->remote = NULL;
|
|
|
|
pfr->addressfamily = ADDRTYPE_UNSPEC;
|
|
|
|
|
|
|
|
PortFwdRecord *existing = add234(mgr->forwardings, pfr);
|
|
|
|
if (existing != pfr) {
|
|
|
|
/*
|
|
|
|
* We had this record already. Return failure.
|
|
|
|
*/
|
|
|
|
pfr_free(pfr);
|
2018-10-29 22:50:29 +03:00
|
|
|
return false;
|
Add an actual SSH server program.
This server is NOT SECURE! If anyone is reading this commit message,
DO NOT DEPLOY IT IN A HOSTILE-FACING ENVIRONMENT! Its purpose is to
speak the server end of everything PuTTY speaks on the client side, so
that I can test that I haven't broken PuTTY when I reorganise its
code, even things like RSA key exchange or chained auth methods which
it's hard to find a server that speaks at all.
(For this reason, it's declared with [UT] in the Recipe file, so that
it falls into the same category as programs like testbn, which won't
be installed by 'make install'.)
Working title is 'Uppity', partly for 'Universal PuTTY Protocol
Interaction Test Yoke', but mostly because it looks quite like the
word 'PuTTY' with part of it reversed. (Apparently 'test yoke' is a
very rarely used term meaning something not altogether unlike 'test
harness', which is a bit of a stretch, but it'll do.)
It doesn't actually _support_ everything I want yet. At the moment,
it's a proof of concept only. But it has most of the machinery
present, and the parts it's missing - such as chained auth methods -
should be easy enough to add because I've built in the required
flexibility, in the form of an AuthPolicy object which can request
them if it wants to. However, the current AuthPolicy object is
entirely trivial, and will let in any user with the password "weasel".
(Another way in which this is not a production-ready server is that it
also has no interaction with the OS's authentication system. In
particular, it will not only let in any user with the same password,
but it won't even change uid - it will open shells and forwardings
under whatever user id you started it up as.)
Currently, the program can only speak the SSH protocol on its standard
I/O channels (using the new FdSocket facility), so if you want it to
listen on a network port, you'll have to run it from some kind of
separate listening program similar to inetd. For my own tests, I'm not
even doing that: I'm just having PuTTY spawn it as a local proxy
process, which also conveniently eliminates the risk of anyone hostile
connecting to it.
The bulk of the actual code reorganisation is already done by previous
commits, so this change is _mostly_ just dropping in a new set of
server-specific source files alongside the client-specific ones I
created recently. The remaining changes in the shared SSH code are
numerous, but all minor:
- a few extra parameters to BPP and PPL constructors (e.g. 'are you
in server mode?'), and pass both sets of SSH-1 protocol flags from
the login to the connection layer
- in server mode, unconditionally send our version string _before_
waiting for the remote one
- a new hook in the SSH-1 BPP to handle enabling compression in
server mode, where the message exchange works the other way round
- new code in the SSH-2 BPP to do _deferred_ compression the other
way round (the non-deferred version is still nicely symmetric)
- in the SSH-2 transport layer, some adjustments to do key derivation
either way round (swapping round the identifying letters in the
various hash preimages, and making sure to list the KEXINITs in the
right order)
- also in the SSH-2 transport layer, an if statement that controls
whether we send SERVICE_REQUEST and wait for SERVICE_ACCEPT, or
vice versa
- new ConnectionLayer methods for opening outgoing channels for X and
agent forwardings
- new functions in portfwd.c to establish listening sockets suitable
for remote-to-local port forwarding (i.e. not under the direction
of a Conf the way it's done on the client side).
2018-10-21 00:09:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
char *err = pfl_listen(keyhost, keyport, host, port,
|
|
|
|
mgr->cl, conf, &pfr->local, pfr->addressfamily);
|
|
|
|
logeventf(mgr->cl->logctx,
|
|
|
|
"%s on port %s:%d to forward to client%s%s",
|
|
|
|
err ? "Failed to listen" : "Listening", host, port,
|
|
|
|
err ? ": " : "", err ? err : "");
|
|
|
|
if (err) {
|
|
|
|
sfree(err);
|
|
|
|
del234(mgr->forwardings, pfr);
|
|
|
|
pfr_free(pfr);
|
2018-10-29 22:50:29 +03:00
|
|
|
return false;
|
Add an actual SSH server program.
This server is NOT SECURE! If anyone is reading this commit message,
DO NOT DEPLOY IT IN A HOSTILE-FACING ENVIRONMENT! Its purpose is to
speak the server end of everything PuTTY speaks on the client side, so
that I can test that I haven't broken PuTTY when I reorganise its
code, even things like RSA key exchange or chained auth methods which
it's hard to find a server that speaks at all.
(For this reason, it's declared with [UT] in the Recipe file, so that
it falls into the same category as programs like testbn, which won't
be installed by 'make install'.)
Working title is 'Uppity', partly for 'Universal PuTTY Protocol
Interaction Test Yoke', but mostly because it looks quite like the
word 'PuTTY' with part of it reversed. (Apparently 'test yoke' is a
very rarely used term meaning something not altogether unlike 'test
harness', which is a bit of a stretch, but it'll do.)
It doesn't actually _support_ everything I want yet. At the moment,
it's a proof of concept only. But it has most of the machinery
present, and the parts it's missing - such as chained auth methods -
should be easy enough to add because I've built in the required
flexibility, in the form of an AuthPolicy object which can request
them if it wants to. However, the current AuthPolicy object is
entirely trivial, and will let in any user with the password "weasel".
(Another way in which this is not a production-ready server is that it
also has no interaction with the OS's authentication system. In
particular, it will not only let in any user with the same password,
but it won't even change uid - it will open shells and forwardings
under whatever user id you started it up as.)
Currently, the program can only speak the SSH protocol on its standard
I/O channels (using the new FdSocket facility), so if you want it to
listen on a network port, you'll have to run it from some kind of
separate listening program similar to inetd. For my own tests, I'm not
even doing that: I'm just having PuTTY spawn it as a local proxy
process, which also conveniently eliminates the risk of anyone hostile
connecting to it.
The bulk of the actual code reorganisation is already done by previous
commits, so this change is _mostly_ just dropping in a new set of
server-specific source files alongside the client-specific ones I
created recently. The remaining changes in the shared SSH code are
numerous, but all minor:
- a few extra parameters to BPP and PPL constructors (e.g. 'are you
in server mode?'), and pass both sets of SSH-1 protocol flags from
the login to the connection layer
- in server mode, unconditionally send our version string _before_
waiting for the remote one
- a new hook in the SSH-1 BPP to handle enabling compression in
server mode, where the message exchange works the other way round
- new code in the SSH-2 BPP to do _deferred_ compression the other
way round (the non-deferred version is still nicely symmetric)
- in the SSH-2 transport layer, some adjustments to do key derivation
either way round (swapping round the identifying letters in the
various hash preimages, and making sure to list the KEXINITs in the
right order)
- also in the SSH-2 transport layer, an if statement that controls
whether we send SERVICE_REQUEST and wait for SERVICE_ACCEPT, or
vice versa
- new ConnectionLayer methods for opening outgoing channels for X and
agent forwardings
- new functions in portfwd.c to establish listening sockets suitable
for remote-to-local port forwarding (i.e. not under the direction
of a Conf the way it's done on the client side).
2018-10-21 00:09:54 +03:00
|
|
|
}
|
|
|
|
|
2018-10-29 22:50:29 +03:00
|
|
|
return true;
|
Add an actual SSH server program.
This server is NOT SECURE! If anyone is reading this commit message,
DO NOT DEPLOY IT IN A HOSTILE-FACING ENVIRONMENT! Its purpose is to
speak the server end of everything PuTTY speaks on the client side, so
that I can test that I haven't broken PuTTY when I reorganise its
code, even things like RSA key exchange or chained auth methods which
it's hard to find a server that speaks at all.
(For this reason, it's declared with [UT] in the Recipe file, so that
it falls into the same category as programs like testbn, which won't
be installed by 'make install'.)
Working title is 'Uppity', partly for 'Universal PuTTY Protocol
Interaction Test Yoke', but mostly because it looks quite like the
word 'PuTTY' with part of it reversed. (Apparently 'test yoke' is a
very rarely used term meaning something not altogether unlike 'test
harness', which is a bit of a stretch, but it'll do.)
It doesn't actually _support_ everything I want yet. At the moment,
it's a proof of concept only. But it has most of the machinery
present, and the parts it's missing - such as chained auth methods -
should be easy enough to add because I've built in the required
flexibility, in the form of an AuthPolicy object which can request
them if it wants to. However, the current AuthPolicy object is
entirely trivial, and will let in any user with the password "weasel".
(Another way in which this is not a production-ready server is that it
also has no interaction with the OS's authentication system. In
particular, it will not only let in any user with the same password,
but it won't even change uid - it will open shells and forwardings
under whatever user id you started it up as.)
Currently, the program can only speak the SSH protocol on its standard
I/O channels (using the new FdSocket facility), so if you want it to
listen on a network port, you'll have to run it from some kind of
separate listening program similar to inetd. For my own tests, I'm not
even doing that: I'm just having PuTTY spawn it as a local proxy
process, which also conveniently eliminates the risk of anyone hostile
connecting to it.
The bulk of the actual code reorganisation is already done by previous
commits, so this change is _mostly_ just dropping in a new set of
server-specific source files alongside the client-specific ones I
created recently. The remaining changes in the shared SSH code are
numerous, but all minor:
- a few extra parameters to BPP and PPL constructors (e.g. 'are you
in server mode?'), and pass both sets of SSH-1 protocol flags from
the login to the connection layer
- in server mode, unconditionally send our version string _before_
waiting for the remote one
- a new hook in the SSH-1 BPP to handle enabling compression in
server mode, where the message exchange works the other way round
- new code in the SSH-2 BPP to do _deferred_ compression the other
way round (the non-deferred version is still nicely symmetric)
- in the SSH-2 transport layer, some adjustments to do key derivation
either way round (swapping round the identifying letters in the
various hash preimages, and making sure to list the KEXINITs in the
right order)
- also in the SSH-2 transport layer, an if statement that controls
whether we send SERVICE_REQUEST and wait for SERVICE_ACCEPT, or
vice versa
- new ConnectionLayer methods for opening outgoing channels for X and
agent forwardings
- new functions in portfwd.c to establish listening sockets suitable
for remote-to-local port forwarding (i.e. not under the direction
of a Conf the way it's done on the client side).
2018-10-21 00:09:54 +03:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
bool portfwdmgr_unlisten(PortFwdManager *mgr, const char *host, int port)
|
Add an actual SSH server program.
This server is NOT SECURE! If anyone is reading this commit message,
DO NOT DEPLOY IT IN A HOSTILE-FACING ENVIRONMENT! Its purpose is to
speak the server end of everything PuTTY speaks on the client side, so
that I can test that I haven't broken PuTTY when I reorganise its
code, even things like RSA key exchange or chained auth methods which
it's hard to find a server that speaks at all.
(For this reason, it's declared with [UT] in the Recipe file, so that
it falls into the same category as programs like testbn, which won't
be installed by 'make install'.)
Working title is 'Uppity', partly for 'Universal PuTTY Protocol
Interaction Test Yoke', but mostly because it looks quite like the
word 'PuTTY' with part of it reversed. (Apparently 'test yoke' is a
very rarely used term meaning something not altogether unlike 'test
harness', which is a bit of a stretch, but it'll do.)
It doesn't actually _support_ everything I want yet. At the moment,
it's a proof of concept only. But it has most of the machinery
present, and the parts it's missing - such as chained auth methods -
should be easy enough to add because I've built in the required
flexibility, in the form of an AuthPolicy object which can request
them if it wants to. However, the current AuthPolicy object is
entirely trivial, and will let in any user with the password "weasel".
(Another way in which this is not a production-ready server is that it
also has no interaction with the OS's authentication system. In
particular, it will not only let in any user with the same password,
but it won't even change uid - it will open shells and forwardings
under whatever user id you started it up as.)
Currently, the program can only speak the SSH protocol on its standard
I/O channels (using the new FdSocket facility), so if you want it to
listen on a network port, you'll have to run it from some kind of
separate listening program similar to inetd. For my own tests, I'm not
even doing that: I'm just having PuTTY spawn it as a local proxy
process, which also conveniently eliminates the risk of anyone hostile
connecting to it.
The bulk of the actual code reorganisation is already done by previous
commits, so this change is _mostly_ just dropping in a new set of
server-specific source files alongside the client-specific ones I
created recently. The remaining changes in the shared SSH code are
numerous, but all minor:
- a few extra parameters to BPP and PPL constructors (e.g. 'are you
in server mode?'), and pass both sets of SSH-1 protocol flags from
the login to the connection layer
- in server mode, unconditionally send our version string _before_
waiting for the remote one
- a new hook in the SSH-1 BPP to handle enabling compression in
server mode, where the message exchange works the other way round
- new code in the SSH-2 BPP to do _deferred_ compression the other
way round (the non-deferred version is still nicely symmetric)
- in the SSH-2 transport layer, some adjustments to do key derivation
either way round (swapping round the identifying letters in the
various hash preimages, and making sure to list the KEXINITs in the
right order)
- also in the SSH-2 transport layer, an if statement that controls
whether we send SERVICE_REQUEST and wait for SERVICE_ACCEPT, or
vice versa
- new ConnectionLayer methods for opening outgoing channels for X and
agent forwardings
- new functions in portfwd.c to establish listening sockets suitable
for remote-to-local port forwarding (i.e. not under the direction
of a Conf the way it's done on the client side).
2018-10-21 00:09:54 +03:00
|
|
|
{
|
|
|
|
PortFwdRecord pfr_key;
|
|
|
|
|
|
|
|
pfr_key.type = 'L';
|
|
|
|
/* Safe to cast the const away here, because it will only be used
|
|
|
|
* by pfr_cmp, which won't write to the string */
|
|
|
|
pfr_key.saddr = pfr_key.daddr = (char *)host;
|
|
|
|
pfr_key.sserv = pfr_key.dserv = NULL;
|
|
|
|
pfr_key.sport = pfr_key.dport = port;
|
|
|
|
pfr_key.local = NULL;
|
|
|
|
pfr_key.remote = NULL;
|
|
|
|
pfr_key.addressfamily = ADDRTYPE_UNSPEC;
|
|
|
|
|
|
|
|
PortFwdRecord *pfr = del234(mgr->forwardings, &pfr_key);
|
|
|
|
|
|
|
|
if (!pfr)
|
2018-10-29 22:50:29 +03:00
|
|
|
return false;
|
Add an actual SSH server program.
This server is NOT SECURE! If anyone is reading this commit message,
DO NOT DEPLOY IT IN A HOSTILE-FACING ENVIRONMENT! Its purpose is to
speak the server end of everything PuTTY speaks on the client side, so
that I can test that I haven't broken PuTTY when I reorganise its
code, even things like RSA key exchange or chained auth methods which
it's hard to find a server that speaks at all.
(For this reason, it's declared with [UT] in the Recipe file, so that
it falls into the same category as programs like testbn, which won't
be installed by 'make install'.)
Working title is 'Uppity', partly for 'Universal PuTTY Protocol
Interaction Test Yoke', but mostly because it looks quite like the
word 'PuTTY' with part of it reversed. (Apparently 'test yoke' is a
very rarely used term meaning something not altogether unlike 'test
harness', which is a bit of a stretch, but it'll do.)
It doesn't actually _support_ everything I want yet. At the moment,
it's a proof of concept only. But it has most of the machinery
present, and the parts it's missing - such as chained auth methods -
should be easy enough to add because I've built in the required
flexibility, in the form of an AuthPolicy object which can request
them if it wants to. However, the current AuthPolicy object is
entirely trivial, and will let in any user with the password "weasel".
(Another way in which this is not a production-ready server is that it
also has no interaction with the OS's authentication system. In
particular, it will not only let in any user with the same password,
but it won't even change uid - it will open shells and forwardings
under whatever user id you started it up as.)
Currently, the program can only speak the SSH protocol on its standard
I/O channels (using the new FdSocket facility), so if you want it to
listen on a network port, you'll have to run it from some kind of
separate listening program similar to inetd. For my own tests, I'm not
even doing that: I'm just having PuTTY spawn it as a local proxy
process, which also conveniently eliminates the risk of anyone hostile
connecting to it.
The bulk of the actual code reorganisation is already done by previous
commits, so this change is _mostly_ just dropping in a new set of
server-specific source files alongside the client-specific ones I
created recently. The remaining changes in the shared SSH code are
numerous, but all minor:
- a few extra parameters to BPP and PPL constructors (e.g. 'are you
in server mode?'), and pass both sets of SSH-1 protocol flags from
the login to the connection layer
- in server mode, unconditionally send our version string _before_
waiting for the remote one
- a new hook in the SSH-1 BPP to handle enabling compression in
server mode, where the message exchange works the other way round
- new code in the SSH-2 BPP to do _deferred_ compression the other
way round (the non-deferred version is still nicely symmetric)
- in the SSH-2 transport layer, some adjustments to do key derivation
either way round (swapping round the identifying letters in the
various hash preimages, and making sure to list the KEXINITs in the
right order)
- also in the SSH-2 transport layer, an if statement that controls
whether we send SERVICE_REQUEST and wait for SERVICE_ACCEPT, or
vice versa
- new ConnectionLayer methods for opening outgoing channels for X and
agent forwardings
- new functions in portfwd.c to establish listening sockets suitable
for remote-to-local port forwarding (i.e. not under the direction
of a Conf the way it's done on the client side).
2018-10-21 00:09:54 +03:00
|
|
|
|
|
|
|
logeventf(mgr->cl->logctx, "Closing listening port %s:%d", host, port);
|
|
|
|
|
|
|
|
pfr_free(pfr);
|
2018-10-29 22:50:29 +03:00
|
|
|
return true;
|
Add an actual SSH server program.
This server is NOT SECURE! If anyone is reading this commit message,
DO NOT DEPLOY IT IN A HOSTILE-FACING ENVIRONMENT! Its purpose is to
speak the server end of everything PuTTY speaks on the client side, so
that I can test that I haven't broken PuTTY when I reorganise its
code, even things like RSA key exchange or chained auth methods which
it's hard to find a server that speaks at all.
(For this reason, it's declared with [UT] in the Recipe file, so that
it falls into the same category as programs like testbn, which won't
be installed by 'make install'.)
Working title is 'Uppity', partly for 'Universal PuTTY Protocol
Interaction Test Yoke', but mostly because it looks quite like the
word 'PuTTY' with part of it reversed. (Apparently 'test yoke' is a
very rarely used term meaning something not altogether unlike 'test
harness', which is a bit of a stretch, but it'll do.)
It doesn't actually _support_ everything I want yet. At the moment,
it's a proof of concept only. But it has most of the machinery
present, and the parts it's missing - such as chained auth methods -
should be easy enough to add because I've built in the required
flexibility, in the form of an AuthPolicy object which can request
them if it wants to. However, the current AuthPolicy object is
entirely trivial, and will let in any user with the password "weasel".
(Another way in which this is not a production-ready server is that it
also has no interaction with the OS's authentication system. In
particular, it will not only let in any user with the same password,
but it won't even change uid - it will open shells and forwardings
under whatever user id you started it up as.)
Currently, the program can only speak the SSH protocol on its standard
I/O channels (using the new FdSocket facility), so if you want it to
listen on a network port, you'll have to run it from some kind of
separate listening program similar to inetd. For my own tests, I'm not
even doing that: I'm just having PuTTY spawn it as a local proxy
process, which also conveniently eliminates the risk of anyone hostile
connecting to it.
The bulk of the actual code reorganisation is already done by previous
commits, so this change is _mostly_ just dropping in a new set of
server-specific source files alongside the client-specific ones I
created recently. The remaining changes in the shared SSH code are
numerous, but all minor:
- a few extra parameters to BPP and PPL constructors (e.g. 'are you
in server mode?'), and pass both sets of SSH-1 protocol flags from
the login to the connection layer
- in server mode, unconditionally send our version string _before_
waiting for the remote one
- a new hook in the SSH-1 BPP to handle enabling compression in
server mode, where the message exchange works the other way round
- new code in the SSH-2 BPP to do _deferred_ compression the other
way round (the non-deferred version is still nicely symmetric)
- in the SSH-2 transport layer, some adjustments to do key derivation
either way round (swapping round the identifying letters in the
various hash preimages, and making sure to list the KEXINITs in the
right order)
- also in the SSH-2 transport layer, an if statement that controls
whether we send SERVICE_REQUEST and wait for SERVICE_ACCEPT, or
vice versa
- new ConnectionLayer methods for opening outgoing channels for X and
agent forwardings
- new functions in portfwd.c to establish listening sockets suitable
for remote-to-local port forwarding (i.e. not under the direction
of a Conf the way it's done on the client side).
2018-10-21 00:09:54 +03:00
|
|
|
}
|
|
|
|
|
2020-01-01 19:46:31 +03:00
|
|
|
struct portfwdmgr_connect_ctx {
|
|
|
|
SockAddr *addr;
|
|
|
|
int port;
|
|
|
|
char *canonical_hostname;
|
|
|
|
Conf *conf;
|
|
|
|
};
|
|
|
|
static Socket *portfwdmgr_connect_helper(void *vctx, Plug *plug)
|
|
|
|
{
|
|
|
|
struct portfwdmgr_connect_ctx *ctx = (struct portfwdmgr_connect_ctx *)vctx;
|
Fix double-free in remote->local forwardings.
This bug applies to both the new stream-based agent forwarding, and
ordinary remote->local TCP port forwardings, because it was introduced
by the preliminary infrastructure in commit 09954a87c.
new_connection() and sk_new() accept a SockAddr *, and take ownership
of it. So it's a mistake to make an address, connect to it, and then
sk_addr_free() it: the free will decrement its reference count to
zero, and then the Socket made by the connection will be holding a
stale pointer. But that's exactly what I was doing in the version of
portfwdmgr_connect() that I rewrote in that refactoring. And then I
made the same error again in commit ae1148267 in the Unix stream-based
agent forwarding.
Now both fixed. Rather than remove the sk_addr_free() to make the code
look more like it used to, I've instead solved the problem by adding
an sk_addr_dup() at the point of making the connection. The idea is
that that should be more robust, in that it will still do the right
thing if portfwdmgr_connect_socket should later change so as not to
call its connect helper function at all.
The new Windows stream-based agent forwarding is unaffected by this
bug, because it calls new_named_pipe_client() with a pathname in
string format, without first wrapping it into a SockAddr.
2020-01-14 22:52:54 +03:00
|
|
|
return new_connection(sk_addr_dup(ctx->addr), ctx->canonical_hostname,
|
|
|
|
ctx->port, false, true, false, false, plug,
|
|
|
|
ctx->conf);
|
2020-01-01 19:46:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-14 19:04:39 +03:00
|
|
|
/*
|
|
|
|
* Called when receiving a PORT OPEN from the server to make a
|
|
|
|
* connection to a destination host.
|
|
|
|
*
|
|
|
|
* On success, returns NULL and fills in *pf_ret. On error, returns a
|
|
|
|
* dynamically allocated error message string.
|
|
|
|
*/
|
|
|
|
char *portfwdmgr_connect(PortFwdManager *mgr, Channel **chan_ret,
|
|
|
|
char *hostname, int port, SshChannel *c,
|
|
|
|
int addressfamily)
|
|
|
|
{
|
2020-01-01 19:46:31 +03:00
|
|
|
struct portfwdmgr_connect_ctx ctx[1];
|
|
|
|
const char *err_retd;
|
|
|
|
char *err_toret;
|
2018-09-14 19:04:39 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to find host.
|
|
|
|
*/
|
2020-01-01 19:46:31 +03:00
|
|
|
ctx->addr = name_lookup(hostname, port, &ctx->canonical_hostname,
|
|
|
|
mgr->conf, addressfamily, NULL, NULL);
|
|
|
|
if ((err_retd = sk_addr_error(ctx->addr)) != NULL) {
|
|
|
|
err_toret = dupstr(err_retd);
|
|
|
|
goto out;
|
2018-09-14 19:04:39 +03:00
|
|
|
}
|
|
|
|
|
2020-01-01 19:46:31 +03:00
|
|
|
ctx->conf = mgr->conf;
|
|
|
|
ctx->port = port;
|
|
|
|
|
|
|
|
err_toret = portfwdmgr_connect_socket(
|
|
|
|
mgr, chan_ret, portfwdmgr_connect_helper, ctx, c);
|
|
|
|
|
|
|
|
out:
|
|
|
|
sk_addr_free(ctx->addr);
|
|
|
|
sfree(ctx->canonical_hostname);
|
|
|
|
return err_toret;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *portfwdmgr_connect_socket(PortFwdManager *mgr, Channel **chan_ret,
|
|
|
|
Socket *(*connect)(void *, Plug *), void *ctx,
|
|
|
|
SshChannel *c)
|
|
|
|
{
|
|
|
|
struct PortForwarding *pf;
|
|
|
|
const char *err;
|
|
|
|
|
2018-09-14 19:04:39 +03:00
|
|
|
pf = new_portfwd_state();
|
|
|
|
*chan_ret = &pf->chan;
|
2018-10-05 09:24:16 +03:00
|
|
|
pf->plug.vt = &PortForwarding_plugvt;
|
2018-09-14 19:04:39 +03:00
|
|
|
pf->chan.initial_fixed_window_size = 0;
|
|
|
|
pf->chan.vt = &PortForwarding_channelvt;
|
2018-10-29 22:50:29 +03:00
|
|
|
pf->input_wanted = true;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
|
|
|
pf->ready = true;
|
2018-09-14 19:04:39 +03:00
|
|
|
pf->c = c;
|
2018-09-17 14:14:00 +03:00
|
|
|
pf->cl = mgr->cl;
|
2018-09-14 19:04:39 +03:00
|
|
|
pf->socks_state = SOCKS_NONE;
|
|
|
|
|
2020-01-01 19:46:31 +03:00
|
|
|
pf->s = connect(ctx, &pf->plug);
|
2018-09-14 19:04:39 +03:00
|
|
|
if ((err = sk_socket_error(pf->s)) != NULL) {
|
|
|
|
char *err_ret = dupstr(err);
|
|
|
|
sk_close(pf->s);
|
|
|
|
free_portfwd_state(pf);
|
|
|
|
*chan_ret = NULL;
|
|
|
|
return err_ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
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
|
|
|
}
|