mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
New protocol: PROT_SSHCONN, bare ssh-connection.
This is the same protocol that PuTTY's connection sharing has been using for years, to communicate between the downstream and upstream PuTTYs. I'm now promoting it to be a first-class member of the protocols list: if you have a server for it, you can select it in the GUI or on the command line, and write out a saved session that specifies it. This would be completely insecure if you used it as an ordinary network protocol, of course. Not only is it non-cryptographic and wide open to eavesdropping and hijacking, but it's not even _authenticated_ - it begins after the userauth phase of SSH. So there isn't even the mild security theatre of entering an easy-to-eavesdrop password, as there is with, say, Telnet. However, that's not what I want to use it for. My aim is to use it for various specialist and niche purposes, all of which involve speaking it over an 8-bit-clean data channel that is already set up, secured and authenticated by other methods. There are lots of examples of such channels: - a userv(1) invocation - the console of a UML kernel - the stdio channels into other kinds of container, such as Docker - the 'adb shell' channel (although it seems quite hard to run a custom binary at the far end of that) - a pair of pipes between PuTTY and a Cygwin helper process - and so on. So this protocol is intended as a convenient way to get a client at one end of any those to run a shell session at the other end. Unlike other approaches, it will give you all the SSH-flavoured amenities you're already used to, like forwarding your SSH agent into the container, or forwarding selected network ports in or out of it, or letting it open a window on your X server, or doing SCP/SFTP style file transfer. Of course another way to get all those amenities would be to run an ordinary SSH server over the same channel - but this approach avoids having to manage a phony password or authentication key, or taking up your CPU time with pointless crypto.
This commit is contained in:
parent
0a09c12edc
commit
22b492c4f6
1
be_all.c
1
be_all.c
@ -27,5 +27,6 @@ const struct BackendVtable *const backends[] = {
|
|||||||
&telnet_backend,
|
&telnet_backend,
|
||||||
&rlogin_backend,
|
&rlogin_backend,
|
||||||
&raw_backend,
|
&raw_backend,
|
||||||
|
&sshconn_backend,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -28,5 +28,6 @@ const struct BackendVtable *const backends[] = {
|
|||||||
&rlogin_backend,
|
&rlogin_backend,
|
||||||
&raw_backend,
|
&raw_backend,
|
||||||
&serial_backend,
|
&serial_backend,
|
||||||
|
&sshconn_backend,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -22,13 +22,26 @@ filled in before PuTTY can open a session at all.
|
|||||||
address}, of the server you want to connect to.
|
address}, of the server you want to connect to.
|
||||||
|
|
||||||
\b The \q{Connection type} radio buttons let you choose what type of
|
\b The \q{Connection type} radio buttons let you choose what type of
|
||||||
connection you want to make: a \I{raw TCP connections}raw
|
connection you want to make: an \i{SSH} network connection, a
|
||||||
connection, a \i{Telnet} connection, an \i{Rlogin} connection, an
|
connection to a local \i{serial line}, or various other kinds of
|
||||||
\i{SSH} connection, or a connection to a local \i{serial line}. (See
|
network connection.
|
||||||
\k{which-one} for a summary of the differences between SSH, Telnet
|
|
||||||
and rlogin; see \k{using-rawprot} for an explanation of \q{raw}
|
\lcont{
|
||||||
connections; see \k{using-serial} for information about using a
|
|
||||||
serial line.)
|
\b See \k{which-one} for a summary of the
|
||||||
|
differences between the network remote login protocols SSH, Telnet and
|
||||||
|
Rlogin.
|
||||||
|
|
||||||
|
\b See \k{using-rawprot} for an explanation of \q{raw}
|
||||||
|
connections.
|
||||||
|
|
||||||
|
\b See \k{using-serial} for information about using a serial line.
|
||||||
|
|
||||||
|
\b The \q{Bare ssh-connection} option in the \q{Connection type} box
|
||||||
|
is experimental, for specialist uses, and servers for it are not
|
||||||
|
widely available.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
\b The \q{Port} box lets you specify which \i{port number} on the
|
\b The \q{Port} box lets you specify which \i{port number} on the
|
||||||
server to connect to. If you select Telnet, Rlogin, or SSH, this box
|
server to connect to. If you select Telnet, Rlogin, or SSH, this box
|
||||||
|
3
putty.h
3
putty.h
@ -365,7 +365,7 @@ enum {
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* Protocol back ends. (CONF_protocol) */
|
/* Protocol back ends. (CONF_protocol) */
|
||||||
PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH,
|
PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH, PROT_SSHCONN,
|
||||||
/* PROT_SERIAL is supported on a subset of platforms, but it doesn't
|
/* PROT_SERIAL is supported on a subset of platforms, but it doesn't
|
||||||
* hurt to define it globally. */
|
* hurt to define it globally. */
|
||||||
PROT_SERIAL,
|
PROT_SERIAL,
|
||||||
@ -1746,6 +1746,7 @@ extern const struct BackendVtable telnet_backend;
|
|||||||
* Exports from ssh.c.
|
* Exports from ssh.c.
|
||||||
*/
|
*/
|
||||||
extern const struct BackendVtable ssh_backend;
|
extern const struct BackendVtable ssh_backend;
|
||||||
|
extern const struct BackendVtable sshconn_backend;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exports from ldisc.c.
|
* Exports from ldisc.c.
|
||||||
|
33
ssh.c
33
ssh.c
@ -311,8 +311,8 @@ static void ssh_got_ssh_version(struct ssh_version_receiver *rcv,
|
|||||||
ssh_connect_bpp(ssh);
|
ssh_connect_bpp(ssh);
|
||||||
|
|
||||||
connection_layer = ssh2_connection_new(
|
connection_layer = ssh2_connection_new(
|
||||||
ssh, NULL, false, ssh->conf, ssh_verstring_get_remote(old_bpp),
|
ssh, ssh->connshare, false, ssh->conf,
|
||||||
&ssh->cl);
|
ssh_verstring_get_remote(old_bpp), &ssh->cl);
|
||||||
ssh_connect_ppl(ssh, connection_layer);
|
ssh_connect_ppl(ssh, connection_layer);
|
||||||
ssh->base_layer = connection_layer;
|
ssh->base_layer = connection_layer;
|
||||||
}
|
}
|
||||||
@ -861,6 +861,11 @@ static void ssh_cache_conf_values(Ssh *ssh)
|
|||||||
ssh->pls.omit_data = conf_get_bool(ssh->conf, CONF_logomitdata);
|
ssh->pls.omit_data = conf_get_bool(ssh->conf, CONF_logomitdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ssh_is_bare(Ssh *ssh)
|
||||||
|
{
|
||||||
|
return ssh->backend.vt->protocol == PROT_SSHCONN;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called to set up the connection.
|
* Called to set up the connection.
|
||||||
*
|
*
|
||||||
@ -894,6 +899,8 @@ static const char *ssh_init(const BackendVtable *vt, Seat *seat,
|
|||||||
ssh->backend.vt = vt;
|
ssh->backend.vt = vt;
|
||||||
*backend_handle = &ssh->backend;
|
*backend_handle = &ssh->backend;
|
||||||
|
|
||||||
|
ssh->bare_connection = (vt->protocol == PROT_SSHCONN);
|
||||||
|
|
||||||
ssh->seat = seat;
|
ssh->seat = seat;
|
||||||
ssh->cl_dummy.logctx = ssh->logctx = logctx;
|
ssh->cl_dummy.logctx = ssh->logctx = logctx;
|
||||||
|
|
||||||
@ -1194,3 +1201,25 @@ const struct BackendVtable ssh_backend = {
|
|||||||
PROT_SSH,
|
PROT_SSH,
|
||||||
22
|
22
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct BackendVtable sshconn_backend = {
|
||||||
|
ssh_init,
|
||||||
|
ssh_free,
|
||||||
|
ssh_reconfig,
|
||||||
|
ssh_send,
|
||||||
|
ssh_sendbuffer,
|
||||||
|
ssh_size,
|
||||||
|
ssh_special,
|
||||||
|
ssh_get_specials,
|
||||||
|
ssh_connected,
|
||||||
|
ssh_return_exitcode,
|
||||||
|
ssh_sendok,
|
||||||
|
ssh_ldisc,
|
||||||
|
ssh_provide_ldisc,
|
||||||
|
ssh_unthrottle,
|
||||||
|
ssh_cfg_info,
|
||||||
|
ssh_test_for_upstream,
|
||||||
|
"ssh-connection", "Bare ssh-connection",
|
||||||
|
PROT_SSHCONN,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
1
ssh.h
1
ssh.h
@ -399,6 +399,7 @@ void ssh_throttle_conn(Ssh *ssh, int adjust);
|
|||||||
void ssh_got_exitcode(Ssh *ssh, int status);
|
void ssh_got_exitcode(Ssh *ssh, int status);
|
||||||
void ssh_ldisc_update(Ssh *ssh);
|
void ssh_ldisc_update(Ssh *ssh);
|
||||||
void ssh_got_fallback_cmd(Ssh *ssh);
|
void ssh_got_fallback_cmd(Ssh *ssh);
|
||||||
|
bool ssh_is_bare(Ssh *ssh);
|
||||||
|
|
||||||
/* Communications back to ssh.c from the BPP */
|
/* Communications back to ssh.c from the BPP */
|
||||||
void ssh_conn_processed_data(Ssh *ssh);
|
void ssh_conn_processed_data(Ssh *ssh);
|
||||||
|
@ -5,8 +5,6 @@ struct outstanding_succfail;
|
|||||||
struct ssh1_connection_state {
|
struct ssh1_connection_state {
|
||||||
int crState;
|
int crState;
|
||||||
|
|
||||||
Ssh *ssh;
|
|
||||||
|
|
||||||
Conf *conf;
|
Conf *conf;
|
||||||
int local_protoflags, remote_protoflags;
|
int local_protoflags, remote_protoflags;
|
||||||
|
|
||||||
|
@ -496,5 +496,6 @@ void ssh2channel_send_terminal_size_change(SshChannel *sc, int w, int h)
|
|||||||
|
|
||||||
bool ssh2_connection_need_antispoof_prompt(struct ssh2_connection_state *s)
|
bool ssh2_connection_need_antispoof_prompt(struct ssh2_connection_state *s)
|
||||||
{
|
{
|
||||||
return !seat_set_trust_status(s->ppl.seat, false);
|
bool success = seat_set_trust_status(s->ppl.seat, false);
|
||||||
|
return (!success && !ssh_is_bare(s->ppl.ssh));
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@ struct outstanding_global_request;
|
|||||||
struct ssh2_connection_state {
|
struct ssh2_connection_state {
|
||||||
int crState;
|
int crState;
|
||||||
|
|
||||||
Ssh *ssh;
|
|
||||||
|
|
||||||
ssh_sharing_state *connshare;
|
ssh_sharing_state *connshare;
|
||||||
char *peer_verstring;
|
char *peer_verstring;
|
||||||
|
|
||||||
|
@ -1993,9 +1993,14 @@ static int share_listen_accepting(Plug *plug,
|
|||||||
*/
|
*/
|
||||||
char *ssh_share_sockname(const char *host, int port, Conf *conf)
|
char *ssh_share_sockname(const char *host, int port, Conf *conf)
|
||||||
{
|
{
|
||||||
char *username = get_remote_username(conf);
|
char *username = NULL;
|
||||||
char *sockname;
|
char *sockname;
|
||||||
|
|
||||||
|
/* Include the username we're logging in as in the hash, unless
|
||||||
|
* we're using a protocol for which it's completely irrelevant. */
|
||||||
|
if (conf_get_int(conf, CONF_protocol) != PROT_SSHCONN)
|
||||||
|
username = get_remote_username(conf);
|
||||||
|
|
||||||
if (port == 22) {
|
if (port == 22) {
|
||||||
if (username)
|
if (username)
|
||||||
sockname = dupprintf("%s@%s", username, host);
|
sockname = dupprintf("%s@%s", username, host);
|
||||||
|
Loading…
Reference in New Issue
Block a user