Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/*
|
|
|
|
* sshproxy.c: implement a Socket type that talks to an entire
|
|
|
|
* subsidiary SSH connection (sometimes called a 'jump host').
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "putty.h"
|
|
|
|
#include "ssh.h"
|
|
|
|
#include "network.h"
|
|
|
|
#include "storage.h"
|
|
|
|
|
|
|
|
const bool ssh_proxy_supported = true;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO for future work:
|
|
|
|
*
|
2021-09-14 11:14:37 +00:00
|
|
|
* All the interactive prompts we present to the main Seat - the host
|
|
|
|
* key and weak-crypto dialog boxes, and all prompts presented via the
|
|
|
|
* userpass_input system - need adjusting so that it's clear to the
|
|
|
|
* user _which_ SSH connection they come from. At the moment, you just
|
|
|
|
* get shown a host key fingerprint or a cryptic "login as:" prompt,
|
|
|
|
* and you have to guess which server you're currently supposed to be
|
|
|
|
* interpreting it relative to.
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
*
|
2021-09-14 11:14:37 +00:00
|
|
|
* If the user manually aborts the attempt to make the proxy SSH
|
|
|
|
* connection (e.g. by hitting ^C at a userpass prompt, or refusing to
|
|
|
|
* accept the proxy server's host key), then an assertion failure
|
|
|
|
* occurs, because the main backend receives an indication of
|
|
|
|
* connection failure that causes it to want to call
|
|
|
|
* seat_connection_fatal("Remote side unexpectedly closed network
|
|
|
|
* connection"), which fails an assertion in tempseat.c because that
|
|
|
|
* method of TempSeat expects never to be called. To fix this, I think
|
|
|
|
* we need to distinguish 'connection attempt unexpectedly failed, in
|
|
|
|
* a way the user needs to be told about' from 'connection attempt was
|
|
|
|
* aborted by deliberate user action, so the user already knows'.
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct SshProxy {
|
|
|
|
char *errmsg;
|
|
|
|
Conf *conf;
|
|
|
|
LogContext *logctx;
|
|
|
|
Backend *backend;
|
2021-09-13 16:17:20 +00:00
|
|
|
LogPolicy *clientlp;
|
2021-09-13 15:30:59 +00:00
|
|
|
Seat *clientseat;
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
|
|
|
|
ProxyStderrBuf psb;
|
|
|
|
Plug *plug;
|
|
|
|
|
|
|
|
bool frozen;
|
|
|
|
bufchain ssh_to_socket;
|
|
|
|
bool rcvd_eof_ssh_to_socket, sent_eof_ssh_to_socket;
|
|
|
|
|
2021-09-12 08:52:46 +00:00
|
|
|
SockAddr *addr;
|
2021-09-12 10:48:42 +00:00
|
|
|
int port;
|
2021-09-12 08:52:46 +00:00
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/* Traits implemented: we're a Socket from the point of view of
|
|
|
|
* the client connection, and a Seat from the POV of the SSH
|
|
|
|
* backend we instantiate. */
|
|
|
|
Socket sock;
|
|
|
|
LogPolicy logpolicy;
|
|
|
|
Seat seat;
|
|
|
|
} SshProxy;
|
|
|
|
|
|
|
|
static Plug *sshproxy_plug(Socket *s, Plug *p)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(s, SshProxy, sock);
|
|
|
|
Plug *oldplug = sp->plug;
|
|
|
|
if (p)
|
|
|
|
sp->plug = p;
|
|
|
|
return oldplug;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sshproxy_close(Socket *s)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(s, SshProxy, sock);
|
|
|
|
|
2021-09-12 08:52:46 +00:00
|
|
|
sk_addr_free(sp->addr);
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
sfree(sp->errmsg);
|
|
|
|
conf_free(sp->conf);
|
|
|
|
if (sp->backend)
|
|
|
|
backend_free(sp->backend);
|
|
|
|
if (sp->logctx)
|
|
|
|
log_free(sp->logctx);
|
|
|
|
bufchain_clear(&sp->ssh_to_socket);
|
|
|
|
|
|
|
|
delete_callbacks_for_context(sp);
|
|
|
|
sfree(sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t sshproxy_write(Socket *s, const void *data, size_t len)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(s, SshProxy, sock);
|
|
|
|
if (!sp->backend)
|
|
|
|
return 0;
|
2021-09-12 08:52:46 +00:00
|
|
|
backend_send(sp->backend, data, len);
|
|
|
|
return backend_sendbuffer(sp->backend);
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static size_t sshproxy_write_oob(Socket *s, const void *data, size_t len)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* oob data is treated as inband; nasty, but nothing really
|
|
|
|
* better we can do
|
|
|
|
*/
|
|
|
|
return sshproxy_write(s, data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sshproxy_write_eof(Socket *s)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(s, SshProxy, sock);
|
|
|
|
if (!sp->backend)
|
|
|
|
return;
|
|
|
|
backend_special(sp->backend, SS_EOF, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void try_send_ssh_to_socket(void *ctx);
|
|
|
|
|
|
|
|
static void sshproxy_set_frozen(Socket *s, bool is_frozen)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(s, SshProxy, sock);
|
|
|
|
sp->frozen = is_frozen;
|
|
|
|
if (!sp->frozen)
|
|
|
|
queue_toplevel_callback(try_send_ssh_to_socket, sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *sshproxy_socket_error(Socket *s)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(s, SshProxy, sock);
|
|
|
|
return sp->errmsg;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SocketPeerInfo *sshproxy_peer_info(Socket *s)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const SocketVtable SshProxy_sock_vt = {
|
|
|
|
.plug = sshproxy_plug,
|
|
|
|
.close = sshproxy_close,
|
|
|
|
.write = sshproxy_write,
|
|
|
|
.write_oob = sshproxy_write_oob,
|
|
|
|
.write_eof = sshproxy_write_eof,
|
|
|
|
.set_frozen = sshproxy_set_frozen,
|
|
|
|
.socket_error = sshproxy_socket_error,
|
|
|
|
.peer_info = sshproxy_peer_info,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void sshproxy_eventlog(LogPolicy *lp, const char *event)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(lp, SshProxy, logpolicy);
|
|
|
|
log_proxy_stderr(sp->plug, &sp->psb, event, strlen(event));
|
|
|
|
log_proxy_stderr(sp->plug, &sp->psb, "\n", 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sshproxy_askappend(LogPolicy *lp, Filename *filename,
|
|
|
|
void (*callback)(void *ctx, int result),
|
|
|
|
void *ctx)
|
|
|
|
{
|
2021-09-13 16:17:20 +00:00
|
|
|
SshProxy *sp = container_of(lp, SshProxy, logpolicy);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have access to the outer LogPolicy, pass on this request
|
|
|
|
* to the end user.
|
|
|
|
*/
|
|
|
|
if (sp->clientlp)
|
|
|
|
return lp_askappend(sp->clientlp, filename, callback, ctx);
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/*
|
2021-09-13 16:17:20 +00:00
|
|
|
* Otherwise, fall back to the safe noninteractive assumption.
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
*/
|
|
|
|
char *msg = dupprintf("Log file \"%s\" already exists; logging cancelled",
|
|
|
|
filename_to_str(filename));
|
|
|
|
sshproxy_eventlog(lp, msg);
|
|
|
|
sfree(msg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sshproxy_logging_error(LogPolicy *lp, const char *event)
|
|
|
|
{
|
2021-09-13 16:17:20 +00:00
|
|
|
SshProxy *sp = container_of(lp, SshProxy, logpolicy);
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/*
|
2021-09-13 16:17:20 +00:00
|
|
|
* If we have access to the outer LogPolicy, pass on this request
|
|
|
|
* to it.
|
|
|
|
*/
|
|
|
|
if (sp->clientlp) {
|
|
|
|
lp_logging_error(sp->clientlp, event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, the best we can do is to put it in the outer SSH
|
|
|
|
* connection's Event Log.
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
*/
|
|
|
|
char *msg = dupprintf("Logging error: %s", event);
|
|
|
|
sshproxy_eventlog(lp, msg);
|
|
|
|
sfree(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const LogPolicyVtable SshProxy_logpolicy_vt = {
|
|
|
|
.eventlog = sshproxy_eventlog,
|
|
|
|
.askappend = sshproxy_askappend,
|
|
|
|
.logging_error = sshproxy_logging_error,
|
|
|
|
.verbose = null_lp_verbose_no,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Function called when we encounter an error during connection setup that's
|
|
|
|
* likely to be the cause of terminating the proxy SSH connection. Putting it
|
|
|
|
* in the Event Log is useful on general principles; also putting it in
|
|
|
|
* sp->errmsg meaks that it will be passed back through plug_closing when the
|
|
|
|
* proxy SSH connection actually terminates, so that the end user will see
|
|
|
|
* what went wrong in the proxy connection.
|
|
|
|
*/
|
|
|
|
static void sshproxy_error(SshProxy *sp, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
char *msg = dupvprintf(fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (!sp->errmsg)
|
|
|
|
sp->errmsg = dupstr(msg);
|
|
|
|
|
|
|
|
sshproxy_eventlog(&sp->logpolicy, msg);
|
|
|
|
sfree(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void try_send_ssh_to_socket(void *ctx)
|
|
|
|
{
|
|
|
|
SshProxy *sp = (SshProxy *)ctx;
|
|
|
|
|
|
|
|
if (sp->frozen)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (bufchain_size(&sp->ssh_to_socket)) {
|
|
|
|
ptrlen pl = bufchain_prefix(&sp->ssh_to_socket);
|
|
|
|
plug_receive(sp->plug, 0, pl.ptr, pl.len);
|
|
|
|
bufchain_consume(&sp->ssh_to_socket, pl.len);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sp->rcvd_eof_ssh_to_socket &&
|
|
|
|
!sp->sent_eof_ssh_to_socket) {
|
|
|
|
sp->sent_eof_ssh_to_socket = true;
|
|
|
|
plug_closing(sp->plug, sp->errmsg, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-12 10:48:42 +00:00
|
|
|
static void sshproxy_notify_session_started(Seat *seat)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
plug_log(sp->plug, PLUGLOG_CONNECT_SUCCESS, sp->addr, sp->port, NULL, 0);
|
|
|
|
}
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
static size_t sshproxy_output(Seat *seat, bool is_stderr,
|
|
|
|
const void *data, size_t len)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
bufchain_add(&sp->ssh_to_socket, data, len);
|
|
|
|
try_send_ssh_to_socket(sp);
|
|
|
|
return bufchain_size(&sp->ssh_to_socket);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool sshproxy_eof(Seat *seat)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
sp->rcvd_eof_ssh_to_socket = true;
|
|
|
|
try_send_ssh_to_socket(sp);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
New Seat callback, seat_sent().
This is used to notify the Seat that some data has been cleared from
the backend's outgoing data buffer. In other words, it notifies the
Seat that it might be worth calling backend_sendbuffer() again.
We've never needed this before, because until now, Seats have always
been the 'main program' part of the application, meaning they were
also in control of the event loop. So they've been able to call
backend_sendbuffer() proactively, every time they go round the event
loop, instead of having to wait for a callback.
But now, the SSH proxy is the first example of a Seat without
privileged access to the event loop, so it has no way to find out that
the backend's sendbuffer has got smaller. And without that, it can't
pass that notification on to plug_sent, to unblock in turn whatever
the proxied connection might have been waiting to send.
In fact, before this commit, sshproxy.c never called plug_sent at all.
As a result, large data uploads over an SSH jump host would hang
forever as soon as the outgoing buffer filled up for the first time:
the main backend (to which sshproxy.c was acting as a Socket) would
carefully stop filling up the buffer, and then never receive the call
to plug_sent that would cause it to start again.
The new callback is ignored everywhere except in sshproxy.c. It might
be a good idea to remove backend_sendbuffer() entirely and convert all
previous uses of it into non-empty implementations of this callback,
so that we've only got one system; but for the moment, I haven't done
that.
2021-06-27 12:52:48 +00:00
|
|
|
static void sshproxy_sent(Seat *seat, size_t new_bufsize)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
plug_sent(sp->plug, new_bufsize);
|
|
|
|
}
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
static void sshproxy_notify_remote_disconnect(Seat *seat)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
if (!sp->rcvd_eof_ssh_to_socket && !backend_connected(sp->backend))
|
|
|
|
sshproxy_eof(seat);
|
|
|
|
}
|
|
|
|
|
Complete rework of terminal userpass input system.
The system for handling seat_get_userpass_input has always been
structured differently between GUI PuTTY and CLI tools like Plink.
In the CLI tools, password input is read directly from the OS
terminal/console device by console_get_userpass_input; this means that
you need to ensure the same terminal input data _hasn't_ already been
consumed by the main event loop and sent on to the backend. This is
achieved by the backend_sendok() method, which tells the event loop
when the backend has finished issuing password prompts, and hence,
when it's safe to start passing standard input to backend_send().
But in the GUI tools, input generated by the terminal window has
always been sent straight to backend_send(), regardless of whether
backend_sendok() says it wants it. So the terminal-based
implementation of username and password prompts has to work by
consuming input data that had _already_ been passed to the backend -
hence, any backend that needs to do that must keep its input on a
bufchain, and pass that bufchain to seat_get_userpass_input.
It's awkward that these two totally different systems coexist in the
first place. And now that SSH proxying needs to present interactive
prompts of its own, it's clear which one should win: the CLI style is
the Right Thing. So this change reworks the GUI side of the mechanism
to be more similar: terminal data now goes into a queue in the Ldisc,
and is not sent on to the backend until the backend says it's ready
for it via backend_sendok(). So terminal-based userpass prompts can
now consume data directly from that queue during the connection setup
stage.
As a result, the 'bufchain *' parameter has vanished from all the
userpass_input functions (both the official implementations of the
Seat trait method, and term_get_userpass_input() to which some of
those implementations delegate). The only function that actually used
that bufchain, namely term_get_userpass_input(), now instead reads
from the ldisc's input queue via a couple of new Ldisc functions.
(Not _trivial_ functions, since input buffered by Ldisc can be a
mixture of raw bytes and session specials like SS_EOL! The input queue
inside Ldisc is a bufchain containing a fiddly binary encoding that
can represent an arbitrary interleaving of those things.)
This greatly simplifies the calls to seat_get_userpass_input in
backends, which now don't have to mess about with passing their own
user_input bufchain around, or toggling their want_user_input flag
back and forth to request data to put on to that bufchain.
But the flip side is that now there has to be some _other_ method for
notifying the terminal when there's more input to be consumed during
an interactive prompt, and for notifying the backend when prompt input
has finished so that it can proceed to the next stage of the protocol.
This is done by a pair of extra callbacks: when more data is put on to
Ldisc's input queue, it triggers a call to term_get_userpass_input,
and when term_get_userpass_input finishes, it calls a callback
function provided in the prompts_t.
Therefore, any use of a prompts_t which *might* be asynchronous must
fill in the latter callback when setting up the prompts_t. In SSH, the
callback is centralised into a common PPL helper function, which
reinvokes the same PPL's process_queue coroutine; in rlogin we have to
set it up ourselves.
I'm sorry for this large and sprawling patch: I tried fairly hard to
break it up into individually comprehensible sub-patches, but I just
couldn't tease out any part of it that would stand sensibly alone.
2021-09-14 10:57:21 +00:00
|
|
|
static int sshproxy_get_userpass_input(Seat *seat, prompts_t *p)
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
{
|
2021-09-14 11:14:37 +00:00
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
|
|
|
|
if (sp->clientseat) {
|
|
|
|
/*
|
|
|
|
* If we have access to the outer Seat, pass this prompt
|
|
|
|
* request on to it. FIXME: appropriately adjusted
|
|
|
|
*/
|
|
|
|
return seat_get_userpass_input(sp->clientseat, p);
|
|
|
|
}
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/*
|
2021-09-14 11:14:37 +00:00
|
|
|
* Otherwise, behave as if noninteractive (like plink -batch):
|
|
|
|
* reject all attempts to present a prompt to the user, and log in
|
|
|
|
* the Event Log to say why not.
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
*/
|
|
|
|
sshproxy_error(sp, "Unable to provide interactive authentication "
|
|
|
|
"requested by proxy SSH connection");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sshproxy_connection_fatal_callback(void *vctx)
|
|
|
|
{
|
|
|
|
SshProxy *sp = (SshProxy *)vctx;
|
|
|
|
plug_closing(sp->plug, sp->errmsg, 0, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sshproxy_connection_fatal(Seat *seat, const char *message)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
if (!sp->errmsg) {
|
|
|
|
sp->errmsg = dupprintf(
|
|
|
|
"fatal error in proxy SSH connection: %s", message);
|
|
|
|
queue_toplevel_callback(sshproxy_connection_fatal_callback, sp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sshproxy_verify_ssh_host_key(
|
|
|
|
Seat *seat, const char *host, int port, const char *keytype,
|
|
|
|
char *keystr, const char *keydisp, char **key_fingerprints,
|
|
|
|
void (*callback)(void *ctx, int result), void *ctx)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
|
2021-09-13 15:30:59 +00:00
|
|
|
if (sp->clientseat) {
|
|
|
|
/*
|
|
|
|
* If we have access to the outer Seat, pass this prompt
|
|
|
|
* request on to it. FIXME: appropriately adjusted
|
|
|
|
*/
|
|
|
|
return seat_verify_ssh_host_key(
|
|
|
|
sp->clientseat, host, port, keytype, keystr, keydisp,
|
|
|
|
key_fingerprints, callback, ctx);
|
|
|
|
}
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/*
|
2021-09-13 15:30:59 +00:00
|
|
|
* Otherwise, behave as if we're in batch mode: directly verify
|
|
|
|
* the host key against the cache, and if that fails, take the
|
|
|
|
* safe option in the absence of interactive confirmation, and
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
* abort the connection.
|
|
|
|
*/
|
|
|
|
int hkstatus = verify_host_key(host, port, keytype, keystr);
|
|
|
|
FingerprintType fptype = ssh2_pick_default_fingerprint(key_fingerprints);
|
|
|
|
|
|
|
|
switch (hkstatus) {
|
|
|
|
case 0: /* host key matched */
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case 1: /* host key not in cache at all */
|
|
|
|
sshproxy_error(sp, "Host key not in cache for %s:%d (fingerprint %s). "
|
|
|
|
"Abandoning proxy SSH connection.", host, port,
|
|
|
|
key_fingerprints[fptype]);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
sshproxy_error(sp, "HOST KEY DOES NOT MATCH CACHE for %s:%d "
|
|
|
|
"(fingerprint %s). Abandoning proxy SSH connection.",
|
|
|
|
host, port, key_fingerprints[fptype]);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
unreachable("bad return value from verify_host_key");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sshproxy_confirm_weak_crypto_primitive(
|
|
|
|
Seat *seat, const char *algtype, const char *algname,
|
|
|
|
void (*callback)(void *ctx, int result), void *ctx)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
|
2021-09-13 15:30:59 +00:00
|
|
|
if (sp->clientseat) {
|
|
|
|
/*
|
|
|
|
* If we have access to the outer Seat, pass this prompt
|
|
|
|
* request on to it. FIXME: appropriately adjusted
|
|
|
|
*/
|
|
|
|
return seat_confirm_weak_crypto_primitive(
|
|
|
|
sp->clientseat, algtype, algname, callback, ctx);
|
|
|
|
}
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/*
|
2021-09-13 15:30:59 +00:00
|
|
|
* Otherwise, behave as if we're in batch mode: take the safest
|
|
|
|
* option.
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
*/
|
|
|
|
sshproxy_error(sp, "First %s supported by server is %s, below warning "
|
|
|
|
"threshold. Abandoning proxy SSH connection.",
|
|
|
|
algtype, algname);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sshproxy_confirm_weak_cached_hostkey(
|
|
|
|
Seat *seat, const char *algname, const char *betteralgs,
|
|
|
|
void (*callback)(void *ctx, int result), void *ctx)
|
|
|
|
{
|
|
|
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
|
|
|
|
2021-09-13 15:30:59 +00:00
|
|
|
if (sp->clientseat) {
|
|
|
|
/*
|
|
|
|
* If we have access to the outer Seat, pass this prompt
|
|
|
|
* request on to it. FIXME: appropriately adjusted
|
|
|
|
*/
|
|
|
|
return seat_confirm_weak_cached_hostkey(
|
|
|
|
sp->clientseat, algname, betteralgs, callback, ctx);
|
|
|
|
}
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/*
|
2021-09-13 15:30:59 +00:00
|
|
|
* Otherwise, behave as if we're in batch mode: take the safest
|
|
|
|
* option.
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
*/
|
|
|
|
sshproxy_error(sp, "First host key type stored for server is %s, below "
|
|
|
|
"warning threshold. Abandoning proxy SSH connection.",
|
|
|
|
algname);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-12 08:52:46 +00:00
|
|
|
static void sshproxy_set_trust_status(Seat *seat, bool trusted)
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This is called by the proxy SSH connection, to set our Seat
|
2021-09-12 08:52:46 +00:00
|
|
|
* into a given trust status. We can safely do nothing here, and
|
|
|
|
* have can_set_trust_status return true to claim we did something
|
|
|
|
* (effectively eliminating the spoofing defences completely, by
|
|
|
|
* suppressing the 'press Return to begin session' prompt and not
|
|
|
|
* providing anything in place of it), on the basis that session
|
|
|
|
* I/O from the proxy SSH connection is never passed directly on
|
|
|
|
* to the end user, so a malicious proxy SSH server wouldn't be
|
|
|
|
* able to spoof our human in any case.
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
*/
|
2021-09-12 08:52:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool sshproxy_can_set_trust_status(Seat *seat)
|
|
|
|
{
|
|
|
|
return true; /* see comment above */
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const SeatVtable SshProxy_seat_vt = {
|
|
|
|
.output = sshproxy_output,
|
|
|
|
.eof = sshproxy_eof,
|
New Seat callback, seat_sent().
This is used to notify the Seat that some data has been cleared from
the backend's outgoing data buffer. In other words, it notifies the
Seat that it might be worth calling backend_sendbuffer() again.
We've never needed this before, because until now, Seats have always
been the 'main program' part of the application, meaning they were
also in control of the event loop. So they've been able to call
backend_sendbuffer() proactively, every time they go round the event
loop, instead of having to wait for a callback.
But now, the SSH proxy is the first example of a Seat without
privileged access to the event loop, so it has no way to find out that
the backend's sendbuffer has got smaller. And without that, it can't
pass that notification on to plug_sent, to unblock in turn whatever
the proxied connection might have been waiting to send.
In fact, before this commit, sshproxy.c never called plug_sent at all.
As a result, large data uploads over an SSH jump host would hang
forever as soon as the outgoing buffer filled up for the first time:
the main backend (to which sshproxy.c was acting as a Socket) would
carefully stop filling up the buffer, and then never receive the call
to plug_sent that would cause it to start again.
The new callback is ignored everywhere except in sshproxy.c. It might
be a good idea to remove backend_sendbuffer() entirely and convert all
previous uses of it into non-empty implementations of this callback,
so that we've only got one system; but for the moment, I haven't done
that.
2021-06-27 12:52:48 +00:00
|
|
|
.sent = sshproxy_sent,
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
.get_userpass_input = sshproxy_get_userpass_input,
|
2021-09-12 10:48:42 +00:00
|
|
|
.notify_session_started = sshproxy_notify_session_started,
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
.notify_remote_exit = nullseat_notify_remote_exit,
|
|
|
|
.notify_remote_disconnect = sshproxy_notify_remote_disconnect,
|
|
|
|
.connection_fatal = sshproxy_connection_fatal,
|
|
|
|
.update_specials_menu = nullseat_update_specials_menu,
|
|
|
|
.get_ttymode = nullseat_get_ttymode,
|
|
|
|
.set_busy_status = nullseat_set_busy_status,
|
|
|
|
.verify_ssh_host_key = sshproxy_verify_ssh_host_key,
|
|
|
|
.confirm_weak_crypto_primitive = sshproxy_confirm_weak_crypto_primitive,
|
|
|
|
.confirm_weak_cached_hostkey = sshproxy_confirm_weak_cached_hostkey,
|
|
|
|
.is_utf8 = nullseat_is_never_utf8,
|
|
|
|
.echoedit_update = nullseat_echoedit_update,
|
|
|
|
.get_x_display = nullseat_get_x_display,
|
|
|
|
.get_windowid = nullseat_get_windowid,
|
|
|
|
.get_window_pixel_size = nullseat_get_window_pixel_size,
|
|
|
|
.stripctrl_new = nullseat_stripctrl_new,
|
|
|
|
.set_trust_status = sshproxy_set_trust_status,
|
2021-09-12 08:52:46 +00:00
|
|
|
.can_set_trust_status = sshproxy_can_set_trust_status,
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
.verbose = nullseat_verbose_no,
|
|
|
|
.interactive = nullseat_interactive_no,
|
|
|
|
.get_cursor_position = nullseat_get_cursor_position,
|
|
|
|
};
|
|
|
|
|
|
|
|
Socket *sshproxy_new_connection(SockAddr *addr, const char *hostname,
|
|
|
|
int port, bool privport,
|
|
|
|
bool oobinline, bool nodelay, bool keepalive,
|
2021-09-13 16:17:20 +00:00
|
|
|
Plug *plug, Conf *clientconf,
|
2021-09-13 15:30:59 +00:00
|
|
|
LogPolicy *clientlp, Seat **clientseat)
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
{
|
|
|
|
SshProxy *sp = snew(SshProxy);
|
|
|
|
memset(sp, 0, sizeof(*sp));
|
|
|
|
|
|
|
|
sp->sock.vt = &SshProxy_sock_vt;
|
|
|
|
sp->logpolicy.vt = &SshProxy_logpolicy_vt;
|
|
|
|
sp->seat.vt = &SshProxy_seat_vt;
|
|
|
|
sp->plug = plug;
|
|
|
|
psb_init(&sp->psb);
|
|
|
|
bufchain_init(&sp->ssh_to_socket);
|
|
|
|
|
2021-09-12 08:52:46 +00:00
|
|
|
sp->addr = addr;
|
2021-09-12 10:48:42 +00:00
|
|
|
sp->port = port;
|
2021-09-12 08:52:46 +00:00
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
sp->conf = conf_new();
|
|
|
|
/* Try to treat proxy_hostname as the title of a saved session. If
|
|
|
|
* that fails, set up a default Conf of our own treating it as a
|
|
|
|
* hostname. */
|
|
|
|
const char *proxy_hostname = conf_get_str(clientconf, CONF_proxy_host);
|
|
|
|
if (do_defaults(proxy_hostname, sp->conf)) {
|
|
|
|
if (!conf_launchable(sp->conf)) {
|
|
|
|
sp->errmsg = dupprintf("saved session '%s' is not launchable",
|
|
|
|
proxy_hostname);
|
|
|
|
return &sp->sock;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
do_defaults(NULL, sp->conf);
|
|
|
|
/* In hostname mode, we default to PROT_SSH. This is more useful than
|
|
|
|
* the obvious approach of defaulting to the protocol defined in
|
|
|
|
* Default Settings, because only SSH (ok, and bare ssh-connection)
|
|
|
|
* can be used for this kind of proxy. */
|
|
|
|
conf_set_int(sp->conf, CONF_protocol, PROT_SSH);
|
|
|
|
conf_set_str(sp->conf, CONF_host, proxy_hostname);
|
|
|
|
conf_set_int(sp->conf, CONF_port,
|
|
|
|
conf_get_int(clientconf, CONF_proxy_port));
|
|
|
|
}
|
|
|
|
const char *proxy_username = conf_get_str(clientconf, CONF_proxy_username);
|
|
|
|
if (*proxy_username)
|
|
|
|
conf_set_str(sp->conf, CONF_username, proxy_username);
|
|
|
|
|
|
|
|
const struct BackendVtable *backvt = backend_vt_from_proto(
|
|
|
|
conf_get_int(sp->conf, CONF_protocol));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't actually need an _SSH_ session specifically: it's also
|
|
|
|
* OK to use PROT_SSHCONN, because really, the criterion is
|
|
|
|
* whether setting CONF_ssh_nc_host will do anything useful. So
|
|
|
|
* our check is for whether the backend sets the flag promising
|
|
|
|
* that it does.
|
|
|
|
*/
|
|
|
|
if (!(backvt->flags & BACKEND_SUPPORTS_NC_HOST)) {
|
|
|
|
sp->errmsg = dupprintf("saved session '%s' is not an SSH session",
|
|
|
|
proxy_hostname);
|
|
|
|
return &sp->sock;
|
|
|
|
}
|
|
|
|
|
2021-09-12 10:48:42 +00:00
|
|
|
/*
|
|
|
|
* We also expect that the backend will announce a willingness to
|
|
|
|
* notify us that the session has started. Any backend providing
|
|
|
|
* NC_HOST should also provide this.
|
|
|
|
*/
|
|
|
|
assert(backvt->flags & BACKEND_NOTIFIES_SESSION_START &&
|
|
|
|
"Backend provides NC_HOST without SESSION_START!");
|
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/*
|
|
|
|
* Turn off SSH features we definitely don't want. It would be
|
|
|
|
* awkward and counterintuitive to have the proxy SSH connection
|
|
|
|
* become a connection-sharing upstream (but it's fine to have it
|
|
|
|
* be a downstream, if that's configured). And we don't want to
|
|
|
|
* open X forwardings, agent forwardings or (other) port
|
|
|
|
* forwardings as a side effect of this one operation.
|
|
|
|
*/
|
|
|
|
conf_set_bool(sp->conf, CONF_ssh_connection_sharing_upstream, false);
|
|
|
|
conf_set_bool(sp->conf, CONF_x11_forward, false);
|
|
|
|
conf_set_bool(sp->conf, CONF_agentfwd, false);
|
|
|
|
for (const char *subkey;
|
|
|
|
(subkey = conf_get_str_nthstrkey(sp->conf, CONF_portfwd, 0)) != NULL;)
|
|
|
|
conf_del_str_str(sp->conf, CONF_portfwd, subkey);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We'll only be running one channel through this connection
|
|
|
|
* (since we've just turned off all the other things we might have
|
|
|
|
* done with it), so we can configure it as simple.
|
|
|
|
*/
|
|
|
|
conf_set_bool(sp->conf, CONF_ssh_simple, true);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Configure the main channel of this SSH session to be a
|
|
|
|
* direct-tcpip connection to the destination host/port.
|
|
|
|
*/
|
|
|
|
conf_set_str(sp->conf, CONF_ssh_nc_host, hostname);
|
|
|
|
conf_set_int(sp->conf, CONF_ssh_nc_port, port);
|
|
|
|
|
|
|
|
sp->logctx = log_init(&sp->logpolicy, sp->conf);
|
|
|
|
|
|
|
|
char *error, *realhost;
|
|
|
|
error = backend_init(backvt, &sp->seat, &sp->backend, sp->logctx, sp->conf,
|
|
|
|
conf_get_str(sp->conf, CONF_host),
|
|
|
|
conf_get_int(sp->conf, CONF_port),
|
|
|
|
&realhost, nodelay,
|
|
|
|
conf_get_bool(sp->conf, CONF_tcp_keepalives));
|
|
|
|
if (error) {
|
|
|
|
sp->errmsg = dupprintf("unable to open SSH proxy connection: %s",
|
|
|
|
error);
|
|
|
|
return &sp->sock;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfree(realhost);
|
|
|
|
|
2021-09-13 15:30:59 +00:00
|
|
|
/*
|
|
|
|
* If we've been given useful bits and pieces for interacting with
|
|
|
|
* the end user, squirrel them away now.
|
|
|
|
*/
|
2021-09-13 16:17:20 +00:00
|
|
|
sp->clientlp = clientlp;
|
2021-09-13 15:30:59 +00:00
|
|
|
if (clientseat && (backvt->flags & BACKEND_NOTIFIES_SESSION_START)) {
|
|
|
|
/*
|
|
|
|
* We can only keep the client's Seat if our own backend will
|
|
|
|
* tell us when to give it back. (SSH-based backends _should_
|
|
|
|
* do that, but we check the flag here anyway.)
|
|
|
|
*
|
|
|
|
* Also, check if the client already has a TempSeat, and if
|
|
|
|
* so, don't wrap it with another one.
|
|
|
|
*/
|
|
|
|
if (is_tempseat(*clientseat)) {
|
|
|
|
sp->clientseat = tempseat_get_real(*clientseat);
|
|
|
|
} else {
|
|
|
|
sp->clientseat = *clientseat;
|
|
|
|
*clientseat = tempseat_new(sp->clientseat);
|
|
|
|
}
|
|
|
|
}
|
2021-09-13 16:17:20 +00:00
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
return &sp->sock;
|
|
|
|
}
|