summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2008-06-13 04:50:27 +1000
committerDarren Tucker <dtucker@zip.com.au>2008-06-13 04:50:27 +1000
commit9f407c4422a7f8283eda674e10755d0b4f1c2413 (patch)
tree64b489e36a0e022ecd27b87c19d7529bf3733464
parent2fb66caca2c9e69c6a0584060114fcd52e59d5ff (diff)
- 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@
-rw-r--r--ChangeLog9
-rw-r--r--clientloop.c49
-rw-r--r--clientloop.h6
-rw-r--r--ssh.c53
4 files changed, 86 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index ca0d8ea57..215f67820 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -78,6 +78,13 @@
78 mux client will not be able to connect to a running old ssh 78 mux client will not be able to connect to a running old ssh
79 mux master. 79 mux master.
80 ok dtucker@ 80 ok dtucker@
81 - djm@cvs.openbsd.org 2008/06/12 04:06:00
82 [clientloop.h ssh.c clientloop.c]
83 maintain an ordered queue of outstanding global requests that we
84 expect replies to, similar to the per-channel confirmation queue.
85 Use this queue to verify success or failure for remote forward
86 establishment in a race free way.
87 ok dtucker@
81 88
8220080611 8920080611
83 - (djm) [channels.c configure.ac] 90 - (djm) [channels.c configure.ac]
@@ -4240,4 +4247,4 @@
4240 OpenServer 6 and add osr5bigcrypt support so when someone migrates 4247 OpenServer 6 and add osr5bigcrypt support so when someone migrates
4241 passwords between UnixWare and OpenServer they will still work. OK dtucker@ 4248 passwords between UnixWare and OpenServer they will still work. OK dtucker@
4242 4249
4243$Id: ChangeLog,v 1.4977 2008/06/12 18:49:33 dtucker Exp $ 4250$Id: ChangeLog,v 1.4978 2008/06/12 18:50:27 dtucker Exp $
diff --git a/clientloop.c b/clientloop.c
index b45e7298a..37cecf5a6 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.195 2008/06/12 03:40:52 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.196 2008/06/12 04:06:00 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -174,6 +174,17 @@ struct channel_reply_ctx {
174 int id, do_close; 174 int id, do_close;
175}; 175};
176 176
177/* Global request success/failure callbacks */
178struct global_confirm {
179 TAILQ_ENTRY(global_confirm) entry;
180 global_confirm_cb *cb;
181 void *ctx;
182 int ref_count;
183};
184TAILQ_HEAD(global_confirms, global_confirm);
185static struct global_confirms global_confirms =
186 TAILQ_HEAD_INITIALIZER(global_confirms);
187
177/*XXX*/ 188/*XXX*/
178extern Kex *xxx_kex; 189extern Kex *xxx_kex;
179 190
@@ -468,8 +479,19 @@ client_check_window_change(void)
468static void 479static void
469client_global_request_reply(int type, u_int32_t seq, void *ctxt) 480client_global_request_reply(int type, u_int32_t seq, void *ctxt)
470{ 481{
482 struct global_confirm *gc;
483
484 if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
485 return;
486 if (gc->cb != NULL)
487 gc->cb(type, seq, gc->ctx);
488 if (--gc->ref_count <= 0) {
489 TAILQ_REMOVE(&global_confirms, gc, entry);
490 bzero(gc, sizeof(*gc));
491 xfree(gc);
492 }
493
471 keep_alive_timeouts = 0; 494 keep_alive_timeouts = 0;
472 client_global_request_reply_fwd(type, seq, ctxt);
473} 495}
474 496
475static void 497static void
@@ -483,6 +505,8 @@ server_alive_check(void)
483 packet_put_cstring("keepalive@openssh.com"); 505 packet_put_cstring("keepalive@openssh.com");
484 packet_put_char(1); /* boolean: want reply */ 506 packet_put_char(1); /* boolean: want reply */
485 packet_send(); 507 packet_send();
508 /* Insert an empty placeholder to maintain ordering */
509 client_register_global_confirm(NULL, NULL);
486} 510}
487 511
488/* 512/*
@@ -702,6 +726,27 @@ client_expect_confirm(int id, const char *request, int do_close)
702 client_abandon_status_confirm, cr); 726 client_abandon_status_confirm, cr);
703} 727}
704 728
729void
730client_register_global_confirm(global_confirm_cb *cb, void *ctx)
731{
732 struct global_confirm *gc, *first_gc;
733
734 /* Coalesce identical callbacks */
735 first_gc = TAILQ_FIRST(&global_confirms);
736 if (first_gc && first_gc->cb == cb && first_gc->ctx == ctx) {
737 if (++first_gc->ref_count >= INT_MAX)
738 fatal("%s: first_gc->ref_count = %d",
739 __func__, first_gc->ref_count);
740 return;
741 }
742
743 gc = xmalloc(sizeof(*gc));
744 gc->cb = cb;
745 gc->ctx = ctx;
746 gc->ref_count = 1;
747 TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
748}
749
705static void 750static void
706process_cmdline(void) 751process_cmdline(void)
707{ 752{
diff --git a/clientloop.h b/clientloop.h
index cecbfb1a8..3353a9a80 100644
--- a/clientloop.h
+++ b/clientloop.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.h,v 1.20 2008/06/12 03:40:52 djm Exp $ */ 1/* $OpenBSD: clientloop.h,v 1.21 2008/06/12 04:06:00 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -50,6 +50,10 @@ int client_request_tun_fwd(int, int, int);
50void *client_new_escape_filter_ctx(int); 50void *client_new_escape_filter_ctx(int);
51int client_simple_escape_filter(Channel *, char *, int); 51int client_simple_escape_filter(Channel *, char *, int);
52 52
53/* Global request confirmation callbacks */
54typedef void global_confirm_cb(int, u_int32_t seq, void *);
55void client_register_global_confirm(global_confirm_cb *, void *);
56
53/* Multiplexing protocol version */ 57/* Multiplexing protocol version */
54#define SSHMUX_VER 2 58#define SSHMUX_VER 2
55 59
diff --git a/ssh.c b/ssh.c
index e3737bb9c..6c39c85b9 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.314 2008/06/10 22:15:23 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.315 2008/06/12 04:06:00 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -164,7 +164,7 @@ Buffer command;
164int subsystem_flag = 0; 164int subsystem_flag = 0;
165 165
166/* # of replies received for global requests */ 166/* # of replies received for global requests */
167static int client_global_request_id = 0; 167static int remote_forward_confirms_received = 0;
168 168
169/* pid of proxycommand child process */ 169/* pid of proxycommand child process */
170pid_t proxy_command_pid = 0; 170pid_t proxy_command_pid = 0;
@@ -817,6 +817,28 @@ main(int ac, char **av)
817 return exit_status; 817 return exit_status;
818} 818}
819 819
820/* Callback for remote forward global requests */
821static void
822ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
823{
824 Forward *rfwd = (Forward *)ctxt;
825
826 debug("remote forward %s for: listen %d, connect %s:%d",
827 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
828 rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
829 if (type == SSH2_MSG_REQUEST_FAILURE) {
830 if (options.exit_on_forward_failure)
831 fatal("Error: remote port forwarding failed for "
832 "listen port %d", rfwd->listen_port);
833 else
834 logit("Warning: remote port forwarding failed for "
835 "listen port %d", rfwd->listen_port);
836 }
837 if (++remote_forward_confirms_received == options.num_remote_forwards)
838 debug("All remote forwarding requests processed");
839 /* XXX fork-after-authentication */
840}
841
820static void 842static void
821ssh_init_forwarding(void) 843ssh_init_forwarding(void)
822{ 844{
@@ -865,6 +887,8 @@ ssh_init_forwarding(void)
865 logit("Warning: Could not request remote " 887 logit("Warning: Could not request remote "
866 "forwarding."); 888 "forwarding.");
867 } 889 }
890 client_register_global_confirm(ssh_confirm_remote_forward,
891 &options.remote_forwards[i]);
868 } 892 }
869 893
870 /* Initiate tunnel forwarding. */ 894 /* Initiate tunnel forwarding. */
@@ -1034,31 +1058,6 @@ ssh_session(void)
1034 options.escape_char : SSH_ESCAPECHAR_NONE, 0); 1058 options.escape_char : SSH_ESCAPECHAR_NONE, 0);
1035} 1059}
1036 1060
1037void
1038client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
1039{
1040 int i;
1041
1042 i = client_global_request_id++;
1043 if (i >= options.num_remote_forwards)
1044 return;
1045 debug("remote forward %s for: listen %d, connect %s:%d",
1046 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1047 options.remote_forwards[i].listen_port,
1048 options.remote_forwards[i].connect_host,
1049 options.remote_forwards[i].connect_port);
1050 if (type == SSH2_MSG_REQUEST_FAILURE) {
1051 if (options.exit_on_forward_failure)
1052 fatal("Error: remote port forwarding failed for "
1053 "listen port %d",
1054 options.remote_forwards[i].listen_port);
1055 else
1056 logit("Warning: remote port forwarding failed for "
1057 "listen port %d",
1058 options.remote_forwards[i].listen_port);
1059 }
1060}
1061
1062/* request pty/x11/agent/tcpfwd/shell for channel */ 1061/* request pty/x11/agent/tcpfwd/shell for channel */
1063static void 1062static void
1064ssh_session2_setup(int id, void *arg) 1063ssh_session2_setup(int id, void *arg)