This is a vtable that wraps up all the functionality required from the
SSH connection layer by associated modules like port forwarding and
connection sharing. This extra layer of indirection adds nothing
useful right now, but when I later separate the SSH-1 and SSH-2
connection layer implementations, it will be convenient for each one
to be able to implement this vtable in terms of its own internal data
structures.
To simplify this vtable, I've moved a lot of the logging duties
relating to connection sharing out of ssh.c into sshshare.c: now it
handles nearly all the logging itself relating to setting up
connection sharing in the first place and downstreams connecting and
disconnecting. The only exception is the 'Reusing a shared connection'
announcement in the console window, which is now done in ssh.c by
detecting downstream status immediately after setup.
The tree234 storing currently active port forwardings - both local and
remote - now lives in portfwd.c, as does the complicated function that
updates it based on a Conf listing the new set of desired forwardings.
Local port forwardings are passed to ssh.c via the same route as
before - once the listening port receives a connection and portfwd.c
knows where it should be directed to (in particular, after the SOCKS
exchange, if any), it calls ssh_send_port_open.
Remote forwardings are now initiated by calling ssh_rportfwd_alloc,
which adds an entry to the rportfwds tree (which _is_ still in ssh.c,
and still confusingly sorted by a different criterion depending on SSH
protocol version) and sends out the appropriate protocol request.
ssh_rportfwd_remove cancels one again, sending a protocol request too.
Those functions look enough like ssh_{alloc,remove}_sharing_rportfwd
that I've merged those into the new pair as well - now allocating an
rportfwd allows you to specify either a destination host/port or a
sharing context, and returns a handy pointer you can use to cancel the
forwarding later.
Clients outside ssh.c - all implementations of Channel - will now not
see the ssh_channel data type itself, but only a subobject of the
interface type SshChannel. All the sshfwd_* functions have become
methods in that interface type's vtable (though, wrapped in the usual
kind of macros, the call sites look identical).
This paves the way for me to split up the SSH-1 and SSH-2 connection
layers and have each one lay out its channel bookkeeping structure as
it sees fit; as long as they each provide an implementation of the
sshfwd_ method family, the types behind that need not look different.
A minor good effect of this is that the sshfwd_ methods are no longer
global symbols, so they don't have to be stubbed in Unix Pageant to
get it to compile.
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.)
I've also replaced the entire SOCKS state machine whose states were
barely-documented literal integers with one that uses an actual enum.
I think the result is a great deal clearer.
In the course of this rewrite I noticed that PuTTY's dynamic port
forwarding had never got round to supporting the SOCKS5 IPv6 address
format - though there was a FIXME comment saying it ought to. So now
it does: if a SOCKS5 client provides a binary IPv6 address (which
PuTTY's _own_ SOCKS5 client, in proxy.c, is quite capable of doing!),
then that will be translated into the usual IPv6 hex literal
representation to put in the "direct-tcpip" channel open request.
Now I've got FROMFIELD, I can rework it so that structures providing
an implementation of the Socket or Plug trait no longer have to have
the vtable pointer as the very first thing in the structure. In
particular, this means that the ProxySocket structure can now directly
implement _both_ the Socket and Plug traits, which is always
_logically_ how it's worked, but previously it had to be implemented
via two separate structs linked to each other.
This is a cleanup I started to notice a need for during the BinarySink
work. It removes a lot of faffing about casting things to char * or
unsigned char * so that some API will accept them, even though lots of
such APIs really take a plain 'block of raw binary data' argument and
don't care what C thinks the signedness of that data might be - they
may well reinterpret it back and forth internally.
So I've tried to arrange for all the function call APIs that ought to
have a void * (or const void *) to have one, and those that need to do
pointer arithmetic on the parameter internally can cast it back at the
top of the function. That saves endless ad-hoc casts at the call
sites.
This removes a lot of pointless duplications of those constants.
Of course, _ideally_, I should upgrade to C99 bool throughout the code
base, replacing TRUE and FALSE with true and false and tagging
variables explicitly as bool when that's what they semantically are.
But that's a much bigger piece of work, and shouldn't block this
trivial cleanup!
If name resolution fails, pfd_connect tries to sfree(dummy_realhost)
when it's completely uninitialised - the failed resolution didn't
write to it, and we also didn't precautionarily initialise it to NULL
first. Now we do the latter.
A lenof() being applied to a non-array, a couple of missing frees on
an error path, and a case in pfd_receive() where we could have gone
round a loop again after freeing the port forwarding structure it was
working on.
We've always had the back-end code unconditionally print 'Looking up
host' before calling name_lookup. But name_lookup doesn't always do an
actual lookup - in cases where the connection will be proxied and
we're configured to let the proxy do the DNS for us, it just calls
sk_nonamelookup to return a dummy SockAddr with the unresolved name
still in it. It's better to print a message that varies depending on
whether we're _really_ doing DNS or not, e.g. so that people can tell
the difference between DNS failure and proxy misconfiguration.
Hence, those log messages are now generated inside name_lookup(),
which takes a couple of extra parameters for the purpose - a frontend
pointer to pass to logevent(), and a reason string so that it can say
what the hostname it's (optionally) looking up is going to be used
for. (The latter is intended for possible use in logging subsidiary
lookups for port forwarding, though the moment I haven't changed
the current setup where those connection setups aren't logged in
detail - we just pass NULL in that situation.)
When anyone connects to a PuTTY tool's listening socket - whether it's
a user of a local->remote port forwarding, a connection-sharing
downstream or a client of Pageant - we'd like to log as much
information as we can find out about where the connection came from.
To that end, I've implemented a function sk_peer_info() in the socket
abstraction, which returns a freeform text string as best it can (or
NULL, if it can't get anything at all) describing the thing at the
other end of the connection. For TCP connections, this is done using
getpeername() to get an IP address and port in the obvious way; for
Unix-domain sockets, we attempt SO_PEERCRED (conditionalised on some
moderately hairy autoconfery) to get the pid and owner of the peer. I
haven't implemented anything for Windows named pipes, but I will if I
hear of anything useful.
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]
The mechanism for constructing a new connection-type Socket when a
listening one receives an incoming connection previously worked by
passing a platform-specific 'OSSocket' type to the plug_accepting
function, which would then call sk_register to wrap it with a proper
Socket instance. This is less flexible than ideal, because it presumes
that only one kind of OS object might ever need to be turned into a
Socket. So I've replaced OSSocket throughout the code base with a pair
of parameters consisting of a function pointer and a context such that
passing the latter to the former returns the appropriate Socket; this
will permit different classes of listening Socket to pass different
function pointers.
In deference to the reality that OSSockets tend to be small integers
or pointer-sized OS handles, I've made the context parameter an
int/pointer union that can hold either of those directly, rather than
the usual approach of making it a plain 'void *' and requiring a
context structure to be dynamically allocated every time.
[originally from svn r10068]
error with pr->c NULL, in which case calling sshfwd_unclean_close on
it will dereference NULL and segfault. Write an alternative error
handling path for that possibility.
(I don't know if it's the only way, but one way this can happen is if
you're doing dynamic forwarding and the socket error occurs during
SOCKS negotiation, in which case no SSH channel has been set up yet
because we haven't yet found out what we want to put in the
direct-tcpip channel open message.)
[originally from svn r10018]
connection, and replace it with sensible dynamically allocated
storage. While I'm at it, get rid of the disgusting dual use between
storing an actual hostname and storing an incoming SOCKS request; we
now have a separate pointer variable for each.
[originally from svn r9903]
subsidiary network modules like portfwd.c. To be called when the
subsidiary module experiences a socket error: it sends an emergency
CHANNEL_CLOSE (not just outgoing CHANNEL_EOF), and immediately deletes
the local side of the channel. (I've invented a new channel type in
ssh.c called CHAN_ZOMBIE, for channels whose original local side has
already been thrown away and they're just hanging around waiting to
receive the acknowledging CHANNEL_CLOSE.)
As a result of this and the last few commits, I can now run a port
forwarding session in which a local socket error occurs on a forwarded
port, and PuTTY now handles it apparently correctly, closing both the
SSH channel and the local socket and then actually recognising that
it's OK to terminate when all _other_ channels have been closed.
Previously the channel corresponding to the duff connection would
linger around (because of net_pending_errors never being called), and
keep being selected on (hence chewing CPU), and inhibit program
termination at the end of the session (because not all channels were
closed).
[originally from svn r9364]
data channels. Should comprehensively fix 'half-closed', in principle,
though it's a big and complicated change and so there's a good chance
I've made at least one mistake somewhere.
All connections should now be rigorous about propagating end-of-file
(or end-of-data-stream, or socket shutdown, or whatever) independently
in both directions, except in frontends with no mechanism for sending
explicit EOF (e.g. interactive terminal windows) or backends which are
basically always used for interactive sessions so it's unlikely that
an application would be depending on independent EOF (telnet, rlogin).
EOF should now never accidentally be sent while there's still buffered
data to go out before it. (May help fix 'portfwd-corrupt', and also I
noticed recently that the ssh main session channel can accidentally
have MSG_EOF sent before the output bufchain is clear, leading to
embarrassment when it subsequently does send the output).
[originally from svn r9279]
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
local socket _before_ calling the SSH setup functions. This makes no
difference to ssh.c itself, but it makes portfwd.c easier to reuse
for other purposes (e.g. as a component of a standalone SOCKS
server), because now ssh_send_port_open() can itself call
pfd_confirm() without the freeze and unfreeze happening in the wrong
order.
[originally from svn r8500]
of polishing to bring them to what I think should in principle be
release quality. Unlike the unfix.org patches themselves, this
checkin enables IPv6 by default; if you want to leave it out, you
have to build with COMPAT=-DNO_IPV6.
I have tested that this compiles on Visual C 7 (so the nightlies
_should_ acquire IPv6 support without missing a beat), but since I
don't have IPv6 set up myself I haven't actually tested that it
_works_. It still seems to make correct IPv4 connections, but that's
all I've been able to verify for myself. Further testing is needed.
[originally from svn r5047]
[this svn revision also touched putty-wishlist]
Change Settings, the port forwarding setup function is run again,
and tags all existing port forwardings as `do not keep'. Then it
iterates through the config in the normal way; when it encounters a
port forwarding which is already in the tree, it tags it `keep'
rather than setting it up from scratch. Finally, it goes through the
tree and removes any that haven't been labelled `keep'. Hence,
editing the list of forwardings in Change Settings has the effect of
cancelling any forwardings you remove, and adding any new ones.
The SSH panel now appears in the reconfig box, and is empty apart
from a message explaining that it has to be there for subpanels of
it to exist. Better wording for this message would be welcome.
[originally from svn r5030]
No very good reason, but I've occasionally wanted to frob it to see if it
makes any difference to problems I'm having, and it was easy.
Tested that it does actually cause keepalives on Windows (with tcpdump);
should also work on Unix. Not implemented on Mac (does nothing), but then
neither is TCP_NODELAY.
Quite a big checkin, much of which is adding `keepalive' alongside `nodelay'
in network function calls.
[originally from svn r4309]
Also fix what I think are a couple of very minor bugs in SOCKS4; one won't
affect anyone AFAIK, and the other is unlikely to cause trouble.
[originally from svn r3497]
BND.{ADDR,PORT}. Besides being clearly wrong, correspondence with
Sascha Schwarz suggests that this can confuse some SOCKS5 clients
(Aventail and sockscap32) which seem to assume that the reply must
have ATYP=1 (IPv4 literal) and so get the length wrong.
Now all replies have ATYP=1 with BND.{ADDR,PORT} = 0.0.0.0:0 -- this
apparently follows practice in OpenSSH. (We don't have enough info to
fill these fields in correctly.)
[originally from svn r3496]
sk_new() on invocation; these functions become responsible for (eventually)
freeing it. The caller must not do anything with 'addr' after it's been passed
in. (Ick.)
Why:
A SOCKS5 crash appears to have been caused by overzealous freeing of
a SockAddr (ssh.c:1.257 [r2492]), which for proxied connections is
squirreled away long-term (and this can't easily be avoided).
It would have been nice to make a copy of the SockAddr, in case the caller has
a use for it, but one of the implementations (uxnet.c) hides a "struct
addrinfo" in there, and we have no defined way to duplicate those. (None of the
current callers _do_ have a further use for the SockAddr.)
As far as I can tell, everything _except_ proxying only needs addr for the
duration of the call, so sk_addr_free()s immediately. If I'm mistaken, it
should at least be easier to find the offending free()...
[originally from svn r3383]
[r2492 == bdd6633970]
ptrs and ints of different size and -Werror makes this serious).
The GTK bits are done by Colin's patch to use GINT_TO_POINTER
(thanks); the uxnet bits are done by cleaning up the rest of the
code. In particular, network.h now typedefs `OSSocket' to be a type
capable of holding whatever the OS's socket data type is that
underlies our socket abstraction. Individual platforms can make this
typedef themselves if they define OSSOCKET_DEFINED to prevent
network.h redoing it; so the Unix OSSocket is now int. Default is
still void *, so other platforms should be unaffected.
[originally from svn r3171]
supports SOCKS 4, SOCKS 4A and SOCKS 5 (well, actually IPv6 in SOCKS
5 isn't supported, but it'll be no difficulty once I actually get
round to it). Thanks to Chas Honton for his `stone soup' patch: I
didn't end up actually using any of his code, but it galvanised me
into doing it properly myself :-)
[originally from svn r3055]
malloc functions, which automatically cast to the same type they're
allocating the size of. Should prevent any future errors involving
mallocing the size of the wrong structure type, and will also make
life easier if we ever need to turn the PuTTY core code from real C
into C++-friendly C. I haven't touched the Mac frontend in this
checkin because I couldn't compile or test it.
[originally from svn r3014]
holdout static I hadn't noticed; unicode.c had one too; and a large
number of statics that were perfectly OK due to being constants have
been made `const', with assorted `const' repercussions all over the
place. I now declare `remove-statics' to be fixed.
[originally from svn r2594]
proxy-indirection network functions (name_lookup, new_connection,
new_listener) takes a `const Config *' as an argument, and extracts
enough information from it before returning to handle that
particular network operation in accordance with the proxy settings
it specifies. This involved {win,ux}net.c due to a `const'
repercussion.
[originally from svn r2567]
SockAddr, which just contains an unresolved hostname and is created
by a stub function in *net.c. It's an error to pass this to most of
the real-meat functions in *net.c; these fake addresses should have
been dealt with by the time they get down that far. proxy.c now
contains name_lookup(), a wrapper on sk_namelookup() which decides
whether or not to do real DNS, and the individual proxy
implementations each deal sensibly with being handed an unresolved
address and avoid ever passing one down to *net.c.
[originally from svn r2353]
well, though it's a lot less useful since you still can't bind to
low-numbered ports of odd loopback IPs. Should work in principle for
SSH2 remote forwardings as well as local ones, but OpenSSH seems
unwilling to cooperate.
[originally from svn r2344]