1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-08 08:58:00 +00:00

Relax criteria for accepting agent-forwarding channel-opens.

Previously, the instant at which we send to the server a request to
enable agent forwarding (the "auth-agent-req@openssh.com" channel
request, or SSH1_CMSG_AGENT_REQUEST_FORWARDING) was also the instant
at which we set a flag indicating that we're prepared to accept
attempts from the server to open a channel to talk to the forwarded
agent. If the server attempts that when we haven't sent a forwarding
request, we treat it with suspicion, and reject it.

But it turns out that at least one SSH server does this, for what
seems to be a _somewhat_ sensible purpose, and OpenSSH accepts it. So,
on the basis that the @openssh.com domain suffix makes them the
arbiters of this part of the spec, I'm following their practice. I've
removed the 'agent_fwd_enabled' flag from both connection layer
implementations, together with the ConnectionLayer method that sets
it; now agent-forwarding CHANNEL_OPENs are gated only on the questions
of whether agent forwarding was permitted in the configuration and
whether an agent actually exists to talk to, and not also whether we
had previously sent a message to the server announcing it.

(The change to this condition is also applied in the SSH-1 agent
forwarding code, mostly for the sake of keeping things parallel where
possible. I think it doesn't actually make a difference in SSH-1,
because in SSH-1, it's not _possible_ for the server to try to open an
agent channel before the main channel is set up, due to the entirely
separate setup phase of the protocol.)

The use case is a proxy host which makes a secondary SSH connection to
a real destination host. A user has run into one of these recently,
announcing a version banner of "SSH-2.0-FudoSSH", which relies on
agent forwarding to authenticate the secondary connection. You connect
to the proxy host and authenticate with a username string of the form
"realusername#real.destination.host", and then, at the start of the
connection protocol, the server immediately opens a channel back to
your SSH agent which it uses to authenticate to the destination host.
And it delays answering any CHANNEL_OPEN requests from the client
until that's all done. For example (seen from the client's POV,
although the server's CHANNEL_OPEN may well have been _sent_ up front
rather than in response to the client's):

client: SSH2_MSG_CHANNEL_OPEN "session"
server: SSH2_MSG_CHANNEL_OPEN "auth-agent@openssh.com"
client: SSH2_MSG_CHANNEL_OPEN_CONFIRMATION to the auth-agent request
        <- data is exchanged on the agent channel; proxy host uses
           that signature to log in to the destination host ->
server: SSH2_MSG_CHANNEL_OPEN_CONFIRMATION to the session request

With PuTTY, this wasn't working, because at the point when the server
sends the auth-agent CHANNEL_OPEN, we had not yet had any opportunity
to send auth-agent-req (because that has to wait until we've had a
CHANNEL_OPEN_CONFIRMATION). So we were rejecting the server's
CHANNEL_OPEN, which broke this workflow:

client: SSH2_MSG_CHANNEL_OPEN "session"
server: SSH2_MSG_CHANNEL_OPEN "auth-agent@openssh.com"
client: SSH2_MSG_CHANNEL_OPEN_FAILURE to the auth-agent request
        (hey, I haven't told you you can do that yet!)
server: SSH2_MSG_CHANNEL_OPEN_FAILURE to the session request
        (in that case, no shell session for you!)
This commit is contained in:
Simon Tatham 2020-12-23 22:26:44 +00:00
parent 04c50b6cfd
commit b4e1110892
8 changed files with 5 additions and 32 deletions

View File

@ -236,7 +236,6 @@ static void mainchan_request_response(Channel *chan, bool success)
if (success) {
ppl_logevent("Agent forwarding enabled");
ssh_enable_agent_fwd(mc->cl);
} else {
ppl_logevent("Agent forwarding refused");
}

9
ssh.h
View File

@ -294,11 +294,10 @@ struct ConnectionLayerVtable {
* channel) what its preference for line-discipline options is. */
void (*set_ldisc_option)(ConnectionLayer *cl, int option, bool value);
/* Communicate to the connection layer whether X and agent
* forwarding were successfully enabled (for purposes of
* knowing whether to accept subsequent channel-opens). */
/* Communicate to the connection layer whether X forwarding was
* successfully enabled (for purposes of knowing whether to accept
* subsequent channel-opens). */
void (*enable_x_fwd)(ConnectionLayer *cl);
void (*enable_agent_fwd)(ConnectionLayer *cl);
/* Communicate to the connection layer whether the main session
* channel currently wants user input. */
@ -370,8 +369,6 @@ static inline void ssh_set_ldisc_option(ConnectionLayer *cl, int opt, bool val)
{ cl->vt->set_ldisc_option(cl, opt, val); }
static inline void ssh_enable_x_fwd(ConnectionLayer *cl)
{ cl->vt->enable_x_fwd(cl); }
static inline void ssh_enable_agent_fwd(ConnectionLayer *cl)
{ cl->vt->enable_agent_fwd(cl); }
static inline void ssh_set_wants_user_input(ConnectionLayer *cl, bool wanted)
{ cl->vt->set_wants_user_input(cl, wanted); }

View File

@ -151,7 +151,7 @@ bool ssh1_handle_direction_specific_packet(
remid = get_uint32(pktin);
/* Refuse if agent forwarding is disabled. */
if (!s->agent_fwd_enabled) {
if (!ssh_agent_forwarding_permitted(&s->cl)) {
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
put_uint32(pktout, remid);

View File

@ -62,7 +62,6 @@ static void ssh1_throttle_all_channels(ConnectionLayer *cl, bool throttled);
static bool ssh1_ldisc_option(ConnectionLayer *cl, int option);
static void ssh1_set_ldisc_option(ConnectionLayer *cl, int option, bool value);
static void ssh1_enable_x_fwd(ConnectionLayer *cl);
static void ssh1_enable_agent_fwd(ConnectionLayer *cl);
static void ssh1_set_wants_user_input(ConnectionLayer *cl, bool wanted);
static const ConnectionLayerVtable ssh1_connlayer_vtable = {
@ -81,7 +80,6 @@ static const ConnectionLayerVtable ssh1_connlayer_vtable = {
.ldisc_option = ssh1_ldisc_option,
.set_ldisc_option = ssh1_set_ldisc_option,
.enable_x_fwd = ssh1_enable_x_fwd,
.enable_agent_fwd = ssh1_enable_agent_fwd,
.set_wants_user_input = ssh1_set_wants_user_input,
/* other methods are NULL */
};
@ -770,14 +768,6 @@ static void ssh1_enable_x_fwd(ConnectionLayer *cl)
s->X11_fwd_enabled = true;
}
static void ssh1_enable_agent_fwd(ConnectionLayer *cl)
{
struct ssh1_connection_state *s =
container_of(cl, struct ssh1_connection_state, cl);
s->agent_fwd_enabled = true;
}
static void ssh1_set_wants_user_input(ConnectionLayer *cl, bool wanted)
{
struct ssh1_connection_state *s =

View File

@ -31,8 +31,6 @@ struct ssh1_connection_state {
struct X11FakeAuth *x11auth;
tree234 *x11authtree;
bool agent_fwd_enabled;
tree234 *rportfwds;
PortFwdManager *portfwdmgr;
bool portfwdmgr_configured;

View File

@ -89,7 +89,7 @@ static ChanopenResult chan_open_forwarded_tcpip(
static ChanopenResult chan_open_auth_agent(
struct ssh2_connection_state *s, SshChannel *sc)
{
if (!s->agent_fwd_enabled) {
if (!ssh_agent_forwarding_permitted(&s->cl)) {
CHANOPEN_RETURN_FAILURE(
SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
("Agent forwarding is not enabled"));

View File

@ -62,7 +62,6 @@ static void ssh2_throttle_all_channels(ConnectionLayer *cl, bool throttled);
static bool ssh2_ldisc_option(ConnectionLayer *cl, int option);
static void ssh2_set_ldisc_option(ConnectionLayer *cl, int option, bool value);
static void ssh2_enable_x_fwd(ConnectionLayer *cl);
static void ssh2_enable_agent_fwd(ConnectionLayer *cl);
static void ssh2_set_wants_user_input(ConnectionLayer *cl, bool wanted);
static const ConnectionLayerVtable ssh2_connlayer_vtable = {
@ -88,7 +87,6 @@ static const ConnectionLayerVtable ssh2_connlayer_vtable = {
.ldisc_option = ssh2_ldisc_option,
.set_ldisc_option = ssh2_set_ldisc_option,
.enable_x_fwd = ssh2_enable_x_fwd,
.enable_agent_fwd = ssh2_enable_agent_fwd,
.set_wants_user_input = ssh2_set_wants_user_input,
};
@ -1694,14 +1692,6 @@ static void ssh2_enable_x_fwd(ConnectionLayer *cl)
s->X11_fwd_enabled = true;
}
static void ssh2_enable_agent_fwd(ConnectionLayer *cl)
{
struct ssh2_connection_state *s =
container_of(cl, struct ssh2_connection_state, cl);
s->agent_fwd_enabled = true;
}
static void ssh2_set_wants_user_input(ConnectionLayer *cl, bool wanted)
{
struct ssh2_connection_state *s =

View File

@ -29,7 +29,6 @@ struct ssh2_connection_state {
tree234 *x11authtree;
bool got_pty;
bool agent_fwd_enabled;
tree234 *rportfwds;
PortFwdManager *portfwdmgr;