diff options
author | Damien Miller <djm@mindrot.org> | 2011-05-05 06:16:22 +0200 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2011-05-05 06:16:22 +0200 |
commit | 6c3eec7ab23d58157ded8a0e6283f93e45390d07 (patch) | |
tree | 3beb55b3ca050613a158865ec350008dcdd0ab72 | |
parent | - djm@cvs.openbsd.org 2011/04/13 04:09:37 (diff) | |
download | openssh-6c3eec7ab23d58157ded8a0e6283f93e45390d07.tar.xz openssh-6c3eec7ab23d58157ded8a0e6283f93e45390d07.zip |
- djm@cvs.openbsd.org 2011/04/17 22:42:42
[PROTOCOL.mux clientloop.c clientloop.h mux.c ssh.1 ssh.c]
allow graceful shutdown of multiplexing: request that a mux server
removes its listener socket and refuse future multiplexing requests;
ok markus@
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | PROTOCOL.mux | 19 | ||||
-rw-r--r-- | clientloop.c | 34 | ||||
-rw-r--r-- | clientloop.h | 4 | ||||
-rw-r--r-- | mux.c | 86 | ||||
-rw-r--r-- | ssh.1 | 6 | ||||
-rw-r--r-- | ssh.c | 4 |
7 files changed, 140 insertions, 18 deletions
@@ -55,6 +55,11 @@ - djm@cvs.openbsd.org 2011/04/13 04:09:37 [ssh-keygen.1] mention valid -b sizes for ECDSA keys; bz#1862 + - djm@cvs.openbsd.org 2011/04/17 22:42:42 + [PROTOCOL.mux clientloop.c clientloop.h mux.c ssh.1 ssh.c] + allow graceful shutdown of multiplexing: request that a mux server + removes its listener socket and refuse future multiplexing requests; + ok markus@ 20110221 - (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the diff --git a/PROTOCOL.mux b/PROTOCOL.mux index 2a5817bd7..05bb14690 100644 --- a/PROTOCOL.mux +++ b/PROTOCOL.mux @@ -149,10 +149,21 @@ The client then sends its standard input and output file descriptors The contents of "reserved" are currently ignored. -A server may reply with a MUX_S_SESSION_OPEED, a MUX_S_PERMISSION_DENIED +A server may reply with a MUX_S_SESSION_OPENED, a MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE. -8. Status messages +8. Requesting shutdown of mux listener + +A client may request the master to stop accepting new multiplexing requests +and remove its listener socket. + + uint32 MUX_C_STOP_LISTENING + uint32 request id + +A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a +MUX_S_FAILURE. + +9. Status messages The MUX_S_OK message is empty: @@ -178,6 +189,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: #define MUX_C_OPEN_FWD 0x10000006 #define MUX_C_CLOSE_FWD 0x10000007 #define MUX_C_NEW_STDIO_FWD 0x10000008 +#define MUX_C_STOP_LISTENING 0x10000009 #define MUX_S_OK 0x80000001 #define MUX_S_PERMISSION_DENIED 0x80000002 #define MUX_S_FAILURE 0x80000003 @@ -192,7 +204,6 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: XXX TODO XXX extended status (e.g. report open channels / forwards) -XXX graceful close (delete listening socket, but keep existing sessions active) XXX lock (maybe) XXX watch in/out traffic (pre/post crypto) XXX inject packet (what about replies) @@ -200,4 +211,4 @@ XXX server->client error/warning notifications XXX port0 rfwd (need custom response message) XXX send signals via mux -$OpenBSD: PROTOCOL.mux,v 1.4 2011/01/31 21:42:15 djm Exp $ +$OpenBSD: PROTOCOL.mux,v 1.5 2011/04/17 22:42:41 djm Exp $ diff --git a/clientloop.c b/clientloop.c index f6c1444a3..502dd982c 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.231 2011/01/16 12:05:59 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.232 2011/04/17 22:42:41 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -265,10 +265,10 @@ static void set_control_persist_exit_time(void) { if (muxserver_sock == -1 || !options.control_persist - || options.control_persist_timeout == 0) + || options.control_persist_timeout == 0) { /* not using a ControlPersist timeout */ control_persist_exit_time = 0; - else if (channel_still_open()) { + } else if (channel_still_open()) { /* some client connections are still open */ if (control_persist_exit_time > 0) debug2("%s: cancel scheduled exit", __func__); @@ -1419,14 +1419,17 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) if (compat20) { session_ident = ssh2_chan_id; - if (escape_char_arg != SSH_ESCAPECHAR_NONE) - channel_register_filter(session_ident, - client_simple_escape_filter, NULL, - client_filter_cleanup, - client_new_escape_filter_ctx(escape_char_arg)); - if (session_ident != -1) + if (session_ident != -1) { + if (escape_char_arg != SSH_ESCAPECHAR_NONE) { + channel_register_filter(session_ident, + client_simple_escape_filter, NULL, + client_filter_cleanup, + client_new_escape_filter_ctx( + escape_char_arg)); + } channel_register_cleanup(session_ident, client_channel_closed, 0); + } } else { /* Check if we should immediately send eof on stdin. */ client_check_initial_eof_on_stdin(); @@ -2122,6 +2125,19 @@ client_init_dispatch(void) client_init_dispatch_15(); } +void +client_stop_mux(void) +{ + if (options.control_path != NULL && muxserver_sock != -1) + unlink(options.control_path); + /* + * If we are in persist mode, signal that we should close when all + * active channels are closed. + */ + if (options.control_persist) + session_closed = 1; +} + /* client specific fatal cleanup */ void cleanup_exit(int i) diff --git a/clientloop.h b/clientloop.h index 52115db6e..37d072906 100644 --- a/clientloop.h +++ b/clientloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.h,v 1.25 2010/06/25 23:15:36 djm Exp $ */ +/* $OpenBSD: clientloop.h,v 1.26 2011/04/17 22:42:41 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -45,6 +45,7 @@ void client_global_request_reply_fwd(int, u_int32_t, void *); void client_session2_setup(int, int, int, const char *, struct termios *, int, Buffer *, char **); int client_request_tun_fwd(int, int, int); +void client_stop_mux(void); /* Escape filter for protocol 2 sessions */ void *client_new_escape_filter_ctx(int); @@ -64,6 +65,7 @@ void client_register_global_confirm(global_confirm_cb *, void *); #define SSHMUX_COMMAND_TERMINATE 3 /* Ask master to exit */ #define SSHMUX_COMMAND_STDIO_FWD 4 /* Open stdio fwd (ssh -W) */ #define SSHMUX_COMMAND_FORWARD 5 /* Forward only, no command */ +#define SSHMUX_COMMAND_STOP 6 /* Disable mux but not conn */ void muxserver_listen(void); void muxclient(const char *); @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.24 2011/01/13 21:54:53 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.25 2011/04/17 22:42:41 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> * @@ -146,6 +146,7 @@ struct mux_master_state { #define MUX_C_OPEN_FWD 0x10000006 #define MUX_C_CLOSE_FWD 0x10000007 #define MUX_C_NEW_STDIO_FWD 0x10000008 +#define MUX_C_STOP_LISTENING 0x10000009 #define MUX_S_OK 0x80000001 #define MUX_S_PERMISSION_DENIED 0x80000002 #define MUX_S_FAILURE 0x80000003 @@ -168,6 +169,7 @@ static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *); static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); +static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *); static const struct { u_int type; @@ -180,6 +182,7 @@ static const struct { { MUX_C_OPEN_FWD, process_mux_open_fwd }, { MUX_C_CLOSE_FWD, process_mux_close_fwd }, { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd }, + { MUX_C_STOP_LISTENING, process_mux_stop_listening }, { 0, NULL } }; @@ -915,6 +918,39 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) return 0; } +static int +process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) +{ + debug("%s: channel %d: stop listening", __func__, c->self); + + if (options.control_master == SSHCTL_MASTER_ASK || + options.control_master == SSHCTL_MASTER_AUTO_ASK) { + if (!ask_permission("Disable further multiplexing on shared " + "connection to %s? ", host)) { + debug2("%s: stop listen refused by user", __func__); + buffer_put_int(r, MUX_S_PERMISSION_DENIED); + buffer_put_int(r, rid); + buffer_put_cstring(r, "Permission denied"); + return 0; + } + } + + if (mux_listener_channel != NULL) { + channel_free(mux_listener_channel); + client_stop_mux(); + xfree(options.control_path); + options.control_path = NULL; + mux_listener_channel = NULL; + muxserver_sock = -1; + } + + /* prepare reply */ + buffer_put_int(r, MUX_S_OK); + buffer_put_int(r, rid); + + return 0; +} + /* Channel callbacks fired on read/write from mux slave fd */ static int mux_master_read_cb(Channel *c) @@ -1813,6 +1849,50 @@ mux_client_request_stdio_fwd(int fd) fatal("%s: master returned unexpected message %u", __func__, type); } +static void +mux_client_request_stop_listening(int fd) +{ + Buffer m; + char *e; + u_int type, rid; + + debug3("%s: entering", __func__); + + buffer_init(&m); + buffer_put_int(&m, MUX_C_STOP_LISTENING); + buffer_put_int(&m, muxclient_request_id); + + if (mux_client_write_packet(fd, &m) != 0) + fatal("%s: write packet: %s", __func__, strerror(errno)); + + buffer_clear(&m); + + /* Read their reply */ + if (mux_client_read_packet(fd, &m) != 0) + fatal("%s: read from master failed: %s", + __func__, strerror(errno)); + + type = buffer_get_int(&m); + if ((rid = buffer_get_int(&m)) != muxclient_request_id) + fatal("%s: out of sequence reply: my id %u theirs %u", + __func__, muxclient_request_id, rid); + switch (type) { + case MUX_S_OK: + break; + case MUX_S_PERMISSION_DENIED: + e = buffer_get_string(&m, NULL); + fatal("Master refused stop listening request: %s", e); + case MUX_S_FAILURE: + e = buffer_get_string(&m, NULL); + fatal("%s: stop listening request failed: %s", __func__, e); + default: + fatal("%s: unexpected response from master 0x%08x", + __func__, type); + } + buffer_free(&m); + muxclient_request_id++; +} + /* Multiplex client main loop. */ void muxclient(const char *path) @@ -1906,6 +1986,10 @@ muxclient(const char *path) case SSHMUX_COMMAND_STDIO_FWD: mux_client_request_stdio_fwd(sock); exit(0); + case SSHMUX_COMMAND_STOP: + mux_client_request_stop_listening(sock); + fprintf(stderr, "Stop listening request sent.\r\n"); + exit(0); default: fatal("unrecognised muxclient_command %d", muxclient_command); } @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.316 2010/11/18 15:01:00 jmc Exp $ -.Dd $Mdocdate: November 18 2010 $ +.\" $OpenBSD: ssh.1,v 1.317 2011/04/17 22:42:41 djm Exp $ +.Dd $Mdocdate: April 17 2011 $ .Dt SSH 1 .Os .Sh NAME @@ -395,6 +395,8 @@ Valid commands are: (request forwardings without command execution) and .Dq exit (request the master to exit). +.Dq stop +(request the master to stop accepting further multiplexing requests). .It Fl o Ar option Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.356 2011/01/06 22:23:53 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.357 2011/04/17 22:42:42 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -345,6 +345,8 @@ main(int ac, char **av) muxclient_command = SSHMUX_COMMAND_FORWARD; else if (strcmp(optarg, "exit") == 0) muxclient_command = SSHMUX_COMMAND_TERMINATE; + else if (strcmp(optarg, "stop") == 0) + muxclient_command = SSHMUX_COMMAND_STOP; else fatal("Invalid multiplex command."); break; |