- djm@cvs.openbsd.org 2008/06/12 04:06:00
[clientloop.h ssh.c clientloop.c] maintain an ordered queue of outstanding global requests that we expect replies to, similar to the per-channel confirmation queue. Use this queue to verify success or failure for remote forward establishment in a race free way. ok dtucker@
This commit is contained in:
parent
2fb66caca2
commit
9f407c4422
|
@ -78,6 +78,13 @@
|
||||||
mux client will not be able to connect to a running old ssh
|
mux client will not be able to connect to a running old ssh
|
||||||
mux master.
|
mux master.
|
||||||
ok dtucker@
|
ok dtucker@
|
||||||
|
- djm@cvs.openbsd.org 2008/06/12 04:06:00
|
||||||
|
[clientloop.h ssh.c clientloop.c]
|
||||||
|
maintain an ordered queue of outstanding global requests that we
|
||||||
|
expect replies to, similar to the per-channel confirmation queue.
|
||||||
|
Use this queue to verify success or failure for remote forward
|
||||||
|
establishment in a race free way.
|
||||||
|
ok dtucker@
|
||||||
|
|
||||||
20080611
|
20080611
|
||||||
- (djm) [channels.c configure.ac]
|
- (djm) [channels.c configure.ac]
|
||||||
|
@ -4240,4 +4247,4 @@
|
||||||
OpenServer 6 and add osr5bigcrypt support so when someone migrates
|
OpenServer 6 and add osr5bigcrypt support so when someone migrates
|
||||||
passwords between UnixWare and OpenServer they will still work. OK dtucker@
|
passwords between UnixWare and OpenServer they will still work. OK dtucker@
|
||||||
|
|
||||||
$Id: ChangeLog,v 1.4977 2008/06/12 18:49:33 dtucker Exp $
|
$Id: ChangeLog,v 1.4978 2008/06/12 18:50:27 dtucker Exp $
|
||||||
|
|
49
clientloop.c
49
clientloop.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: clientloop.c,v 1.195 2008/06/12 03:40:52 djm Exp $ */
|
/* $OpenBSD: clientloop.c,v 1.196 2008/06/12 04:06:00 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -174,6 +174,17 @@ struct channel_reply_ctx {
|
||||||
int id, do_close;
|
int id, do_close;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Global request success/failure callbacks */
|
||||||
|
struct global_confirm {
|
||||||
|
TAILQ_ENTRY(global_confirm) entry;
|
||||||
|
global_confirm_cb *cb;
|
||||||
|
void *ctx;
|
||||||
|
int ref_count;
|
||||||
|
};
|
||||||
|
TAILQ_HEAD(global_confirms, global_confirm);
|
||||||
|
static struct global_confirms global_confirms =
|
||||||
|
TAILQ_HEAD_INITIALIZER(global_confirms);
|
||||||
|
|
||||||
/*XXX*/
|
/*XXX*/
|
||||||
extern Kex *xxx_kex;
|
extern Kex *xxx_kex;
|
||||||
|
|
||||||
|
@ -468,8 +479,19 @@ client_check_window_change(void)
|
||||||
static void
|
static void
|
||||||
client_global_request_reply(int type, u_int32_t seq, void *ctxt)
|
client_global_request_reply(int type, u_int32_t seq, void *ctxt)
|
||||||
{
|
{
|
||||||
|
struct global_confirm *gc;
|
||||||
|
|
||||||
|
if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
|
||||||
|
return;
|
||||||
|
if (gc->cb != NULL)
|
||||||
|
gc->cb(type, seq, gc->ctx);
|
||||||
|
if (--gc->ref_count <= 0) {
|
||||||
|
TAILQ_REMOVE(&global_confirms, gc, entry);
|
||||||
|
bzero(gc, sizeof(*gc));
|
||||||
|
xfree(gc);
|
||||||
|
}
|
||||||
|
|
||||||
keep_alive_timeouts = 0;
|
keep_alive_timeouts = 0;
|
||||||
client_global_request_reply_fwd(type, seq, ctxt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -483,6 +505,8 @@ server_alive_check(void)
|
||||||
packet_put_cstring("keepalive@openssh.com");
|
packet_put_cstring("keepalive@openssh.com");
|
||||||
packet_put_char(1); /* boolean: want reply */
|
packet_put_char(1); /* boolean: want reply */
|
||||||
packet_send();
|
packet_send();
|
||||||
|
/* Insert an empty placeholder to maintain ordering */
|
||||||
|
client_register_global_confirm(NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -702,6 +726,27 @@ client_expect_confirm(int id, const char *request, int do_close)
|
||||||
client_abandon_status_confirm, cr);
|
client_abandon_status_confirm, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_register_global_confirm(global_confirm_cb *cb, void *ctx)
|
||||||
|
{
|
||||||
|
struct global_confirm *gc, *first_gc;
|
||||||
|
|
||||||
|
/* Coalesce identical callbacks */
|
||||||
|
first_gc = TAILQ_FIRST(&global_confirms);
|
||||||
|
if (first_gc && first_gc->cb == cb && first_gc->ctx == ctx) {
|
||||||
|
if (++first_gc->ref_count >= INT_MAX)
|
||||||
|
fatal("%s: first_gc->ref_count = %d",
|
||||||
|
__func__, first_gc->ref_count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gc = xmalloc(sizeof(*gc));
|
||||||
|
gc->cb = cb;
|
||||||
|
gc->ctx = ctx;
|
||||||
|
gc->ref_count = 1;
|
||||||
|
TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_cmdline(void)
|
process_cmdline(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: clientloop.h,v 1.20 2008/06/12 03:40:52 djm Exp $ */
|
/* $OpenBSD: clientloop.h,v 1.21 2008/06/12 04:06:00 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -50,6 +50,10 @@ int client_request_tun_fwd(int, int, int);
|
||||||
void *client_new_escape_filter_ctx(int);
|
void *client_new_escape_filter_ctx(int);
|
||||||
int client_simple_escape_filter(Channel *, char *, int);
|
int client_simple_escape_filter(Channel *, char *, int);
|
||||||
|
|
||||||
|
/* Global request confirmation callbacks */
|
||||||
|
typedef void global_confirm_cb(int, u_int32_t seq, void *);
|
||||||
|
void client_register_global_confirm(global_confirm_cb *, void *);
|
||||||
|
|
||||||
/* Multiplexing protocol version */
|
/* Multiplexing protocol version */
|
||||||
#define SSHMUX_VER 2
|
#define SSHMUX_VER 2
|
||||||
|
|
||||||
|
|
53
ssh.c
53
ssh.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh.c,v 1.314 2008/06/10 22:15:23 djm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.315 2008/06/12 04:06:00 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -164,7 +164,7 @@ Buffer command;
|
||||||
int subsystem_flag = 0;
|
int subsystem_flag = 0;
|
||||||
|
|
||||||
/* # of replies received for global requests */
|
/* # of replies received for global requests */
|
||||||
static int client_global_request_id = 0;
|
static int remote_forward_confirms_received = 0;
|
||||||
|
|
||||||
/* pid of proxycommand child process */
|
/* pid of proxycommand child process */
|
||||||
pid_t proxy_command_pid = 0;
|
pid_t proxy_command_pid = 0;
|
||||||
|
@ -817,6 +817,28 @@ main(int ac, char **av)
|
||||||
return exit_status;
|
return exit_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for remote forward global requests */
|
||||||
|
static void
|
||||||
|
ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||||
|
{
|
||||||
|
Forward *rfwd = (Forward *)ctxt;
|
||||||
|
|
||||||
|
debug("remote forward %s for: listen %d, connect %s:%d",
|
||||||
|
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
|
||||||
|
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
|
||||||
|
if (type == SSH2_MSG_REQUEST_FAILURE) {
|
||||||
|
if (options.exit_on_forward_failure)
|
||||||
|
fatal("Error: remote port forwarding failed for "
|
||||||
|
"listen port %d", rfwd->listen_port);
|
||||||
|
else
|
||||||
|
logit("Warning: remote port forwarding failed for "
|
||||||
|
"listen port %d", rfwd->listen_port);
|
||||||
|
}
|
||||||
|
if (++remote_forward_confirms_received == options.num_remote_forwards)
|
||||||
|
debug("All remote forwarding requests processed");
|
||||||
|
/* XXX fork-after-authentication */
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ssh_init_forwarding(void)
|
ssh_init_forwarding(void)
|
||||||
{
|
{
|
||||||
|
@ -865,6 +887,8 @@ ssh_init_forwarding(void)
|
||||||
logit("Warning: Could not request remote "
|
logit("Warning: Could not request remote "
|
||||||
"forwarding.");
|
"forwarding.");
|
||||||
}
|
}
|
||||||
|
client_register_global_confirm(ssh_confirm_remote_forward,
|
||||||
|
&options.remote_forwards[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initiate tunnel forwarding. */
|
/* Initiate tunnel forwarding. */
|
||||||
|
@ -1034,31 +1058,6 @@ ssh_session(void)
|
||||||
options.escape_char : SSH_ESCAPECHAR_NONE, 0);
|
options.escape_char : SSH_ESCAPECHAR_NONE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
i = client_global_request_id++;
|
|
||||||
if (i >= options.num_remote_forwards)
|
|
||||||
return;
|
|
||||||
debug("remote forward %s for: listen %d, connect %s:%d",
|
|
||||||
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
|
|
||||||
options.remote_forwards[i].listen_port,
|
|
||||||
options.remote_forwards[i].connect_host,
|
|
||||||
options.remote_forwards[i].connect_port);
|
|
||||||
if (type == SSH2_MSG_REQUEST_FAILURE) {
|
|
||||||
if (options.exit_on_forward_failure)
|
|
||||||
fatal("Error: remote port forwarding failed for "
|
|
||||||
"listen port %d",
|
|
||||||
options.remote_forwards[i].listen_port);
|
|
||||||
else
|
|
||||||
logit("Warning: remote port forwarding failed for "
|
|
||||||
"listen port %d",
|
|
||||||
options.remote_forwards[i].listen_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* request pty/x11/agent/tcpfwd/shell for channel */
|
/* request pty/x11/agent/tcpfwd/shell for channel */
|
||||||
static void
|
static void
|
||||||
ssh_session2_setup(int id, void *arg)
|
ssh_session2_setup(int id, void *arg)
|
||||||
|
|
Loading…
Reference in New Issue