diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | clientloop.c | 49 | ||||
-rw-r--r-- | clientloop.h | 6 | ||||
-rw-r--r-- | ssh.c | 53 |
4 files changed, 86 insertions, 31 deletions
@@ -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 | ||
82 | 20080611 | 89 | 20080611 |
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 */ | ||
178 | struct global_confirm { | ||
179 | TAILQ_ENTRY(global_confirm) entry; | ||
180 | global_confirm_cb *cb; | ||
181 | void *ctx; | ||
182 | int ref_count; | ||
183 | }; | ||
184 | TAILQ_HEAD(global_confirms, global_confirm); | ||
185 | static struct global_confirms global_confirms = | ||
186 | TAILQ_HEAD_INITIALIZER(global_confirms); | ||
187 | |||
177 | /*XXX*/ | 188 | /*XXX*/ |
178 | extern Kex *xxx_kex; | 189 | extern Kex *xxx_kex; |
179 | 190 | ||
@@ -468,8 +479,19 @@ client_check_window_change(void) | |||
468 | static void | 479 | static void |
469 | client_global_request_reply(int type, u_int32_t seq, void *ctxt) | 480 | client_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 | ||
475 | static void | 497 | static 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 | ||
729 | void | ||
730 | client_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 | |||
705 | static void | 750 | static void |
706 | process_cmdline(void) | 751 | process_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); | |||
50 | void *client_new_escape_filter_ctx(int); | 50 | void *client_new_escape_filter_ctx(int); |
51 | int client_simple_escape_filter(Channel *, char *, int); | 51 | int client_simple_escape_filter(Channel *, char *, int); |
52 | 52 | ||
53 | /* Global request confirmation callbacks */ | ||
54 | typedef void global_confirm_cb(int, u_int32_t seq, void *); | ||
55 | void 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 | ||
@@ -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; | |||
164 | int subsystem_flag = 0; | 164 | int subsystem_flag = 0; |
165 | 165 | ||
166 | /* # of replies received for global requests */ | 166 | /* # of replies received for global requests */ |
167 | static int client_global_request_id = 0; | 167 | static int remote_forward_confirms_received = 0; |
168 | 168 | ||
169 | /* pid of proxycommand child process */ | 169 | /* pid of proxycommand child process */ |
170 | pid_t proxy_command_pid = 0; | 170 | pid_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 */ | ||
821 | static void | ||
822 | ssh_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 | |||
820 | static void | 842 | static void |
821 | ssh_init_forwarding(void) | 843 | ssh_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 | ||
1037 | void | ||
1038 | client_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 */ |
1063 | static void | 1062 | static void |
1064 | ssh_session2_setup(int id, void *arg) | 1063 | ssh_session2_setup(int id, void *arg) |