]> andersk Git - openssh.git/commitdiff
- djm@cvs.openbsd.org 2004/11/07 00:01:46
authordtucker <dtucker>
Sun, 7 Nov 2004 09:06:19 +0000 (09:06 +0000)
committerdtucker <dtucker>
Sun, 7 Nov 2004 09:06:19 +0000 (09:06 +0000)
     [clientloop.c clientloop.h ssh.1 ssh.c]
     add basic control of a running multiplex master connection; including the
     ability to check its status and request it to exit; ok markus@

ChangeLog
clientloop.c
clientloop.h
ssh.1
ssh.c

index 101ba2c62895b56478255d9d454959fb82f16349..11cf191216e743abfd3b8a26ef259a29c106c4af 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,10 @@
      [sftp.c]
      command editing and history support via libedit; ok markus@
      thanks to hshoexer@ and many testers on tech@ too
+   - djm@cvs.openbsd.org 2004/11/07 00:01:46
+     [clientloop.c clientloop.h ssh.1 ssh.c]
+     add basic control of a running multiplex master connection; including the
+     ability to check its status and request it to exit; ok markus@
 
 20041105
  - (dtucker) OpenBSD CVS Sync
index d77337b826b277393e335b3f28008d8b09766e23..033a98a5b97fccfbe7479861b36ad723bddff60c 100644 (file)
@@ -59,7 +59,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: clientloop.c,v 1.133 2004/10/29 22:53:56 djm Exp $");
+RCSID("$OpenBSD: clientloop.c,v 1.134 2004/11/07 00:01:46 djm Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -561,7 +561,7 @@ client_process_control(fd_set * readset)
        struct sockaddr_storage addr;
        struct confirm_ctx *cctx;
        char *cmd;
-       u_int len, env_len;
+       u_int len, env_len, command, flags;
        uid_t euid;
        gid_t egid;
 
@@ -591,24 +591,74 @@ client_process_control(fd_set * readset)
                return;
        }
 
-       allowed = 1;
-       if (options.control_master == 2)
-               allowed = ask_permission("Allow shared connection to %s? ",
-                   host);
-
        unset_nonblock(client_fd);
 
+       /* Read command */
        buffer_init(&m);
+       if (ssh_msg_recv(client_fd, &m) == -1) {
+               error("%s: client msg_recv failed", __func__);
+               close(client_fd);
+               buffer_free(&m);
+               return;
+       }
+       if ((ver = buffer_get_char(&m)) != 1) {
+               error("%s: wrong client version %d", __func__, ver);
+               buffer_free(&m);
+               close(client_fd);
+               return;
+       }
+
+       allowed = 1;
+       command = buffer_get_int(&m);
+       flags = buffer_get_int(&m);
+
+       buffer_clear(&m);
 
+       switch (command) {
+       case SSHMUX_COMMAND_OPEN:
+               if (options.control_master == 2)
+                       allowed = ask_permission("Allow shared connection "
+                           "to %s? ", host);
+               /* continue below */
+               break;
+       case SSHMUX_COMMAND_TERMINATE:
+               if (options.control_master == 2)
+                       allowed = ask_permission("Terminate shared connection "
+                           "to %s? ", host);
+               if (allowed)
+                       quit_pending = 1;
+               /* FALLTHROUGH */       
+       case SSHMUX_COMMAND_ALIVE_CHECK:
+               /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
+               buffer_clear(&m);
+               buffer_put_int(&m, allowed);
+               buffer_put_int(&m, getpid());
+               if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
+                       error("%s: client msg_send failed", __func__);
+                       close(client_fd);
+                       buffer_free(&m);
+                       return;
+               }
+               buffer_free(&m);
+               close(client_fd);
+               return;
+       default:
+               error("Unsupported command %d", command);
+               buffer_free(&m);
+               close(client_fd);
+               return;
+       }
+
+       /* Reply for SSHMUX_COMMAND_OPEN */
+       buffer_clear(&m);
        buffer_put_int(&m, allowed);
        buffer_put_int(&m, getpid());
-       if (ssh_msg_send(client_fd, /* version */0, &m) == -1) {
+       if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
                error("%s: client msg_send failed", __func__);
                close(client_fd);
                buffer_free(&m);
                return;
        }
-       buffer_clear(&m);
 
        if (!allowed) {
                error("Refused control connection");
@@ -617,14 +667,14 @@ client_process_control(fd_set * readset)
                return;
        }
 
+       buffer_clear(&m);
        if (ssh_msg_recv(client_fd, &m) == -1) {
                error("%s: client msg_recv failed", __func__);
                close(client_fd);
                buffer_free(&m);
                return;
        }
-
-       if ((ver = buffer_get_char(&m)) != 0) {
+       if ((ver = buffer_get_char(&m)) != 1) {
                error("%s: wrong client version %d", __func__, ver);
                buffer_free(&m);
                close(client_fd);
@@ -633,9 +683,8 @@ client_process_control(fd_set * readset)
 
        cctx = xmalloc(sizeof(*cctx));
        memset(cctx, 0, sizeof(*cctx));
-
-       cctx->want_tty = buffer_get_int(&m);
-       cctx->want_subsys = buffer_get_int(&m);
+       cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
+       cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
        cctx->term = buffer_get_string(&m, &len);
 
        cmd = buffer_get_string(&m, &len);
@@ -667,14 +716,21 @@ client_process_control(fd_set * readset)
        if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
                error("%s: tcgetattr: %s", __func__, strerror(errno));
 
+       /* This roundtrip is just for synchronisation of ttymodes */
        buffer_clear(&m);
-       if (ssh_msg_send(client_fd, /* version */0, &m) == -1) {
+       if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
                error("%s: client msg_send failed", __func__);
                close(client_fd);
                close(new_fd[0]);
                close(new_fd[1]);
                close(new_fd[2]);
                buffer_free(&m);
+               xfree(cctx->term);
+               if (env_len != 0) {
+                       for (i = 0; i < env_len; i++)
+                               xfree(cctx->env[i]);
+                       xfree(cctx->env);
+               }
                return;
        }
        buffer_free(&m);
index 9992d5938b0810b835613de93b84ca922bb67e83..b23c111cbd6cc51954247d2117c7d9be53284a19 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: clientloop.h,v 1.11 2004/07/11 17:48:47 deraadt Exp $ */
+/*     $OpenBSD: clientloop.h,v 1.12 2004/11/07 00:01:46 djm Exp $     */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -40,3 +40,11 @@ int   client_loop(int, int, int);
 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 **, dispatch_fn *);
+
+/* Multiplexing control protocol flags */
+#define SSHMUX_COMMAND_OPEN            1       /* Open new connection */
+#define SSHMUX_COMMAND_ALIVE_CHECK     2       /* Check master is alive */
+#define SSHMUX_COMMAND_TERMINATE       3       /* Ask master to exit */
+
+#define SSHMUX_FLAG_TTY                        (1)     /* Request tty on open */
+#define SSHMUX_FLAG_SUBSYS             (1<<1)  /* Subsystem request on open */
diff --git a/ssh.1 b/ssh.1
index 06cb60cec19d02d3fb313ae23cdb2a4d601ee50f..ec83319b828117a0f3211f05b69476d17cbe2fb7 100644 (file)
--- a/ssh.1
+++ b/ssh.1
@@ -34,7 +34,7 @@
 .\" (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.197 2004/10/07 10:10:24 djm Exp $
+.\" $OpenBSD: ssh.1,v 1.198 2004/11/07 00:01:46 djm Exp $
 .Dd September 25, 1999
 .Dt SSH 1
 .Os
@@ -62,6 +62,7 @@
 .Ek
 .Op Fl l Ar login_name
 .Op Fl m Ar mac_spec
+.Op Fl O Ar ctl_cmd
 .Op Fl o Ar option
 .Bk -words
 .Op Fl p Ar port
@@ -74,7 +75,7 @@
 .Sm on
 .Xc
 .Oc
-.Op Fl S Ar ctl
+.Op Fl S Ar ctl_path
 .Oo Ar user Ns @ Oc Ns Ar hostname
 .Op Ar command
 .Sh DESCRIPTION
@@ -613,6 +614,18 @@ be specified in order of preference.
 See the
 .Cm MACs
 keyword for more information.
+.It Fl O Ar ctl_cmd
+Control an active connection multiplexing master process.
+When the
+.Fl O
+option is specified, the 
+.Ar ctl_cmd
+argument is interpreted and passed to the master process.
+Valid commands are:
+.Dq check
+(check that the master process is running) and 
+.Dq exit
+(request the master to exit).
 .It Fl N
 Do not execute a remote command.
 This is useful for just forwarding ports
@@ -735,7 +748,7 @@ IPv6 addresses can be specified with an alternative syntax:
 .Ar hostport .
 .Xc
 .Sm on
-.It Fl S Ar ctl
+.It Fl S Ar ctl_path
 Specifies the location of a control socket for connection sharing.
 Refer to the description of
 .Cm ControlPath
diff --git a/ssh.c b/ssh.c
index c231c5fae5c266b9ca491515d4614357b75a2669..dfe9b25c1e474fb26d7124897c8083cc3021aeda 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -40,7 +40,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.228 2004/09/23 13:00:04 djm Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.229 2004/11/07 00:01:46 djm Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/err.h>
@@ -144,6 +144,9 @@ pid_t proxy_command_pid = 0;
 /* fd to control socket */
 int control_fd = -1;
 
+/* Multiplexing control command */
+static u_int mux_command = SSHMUX_COMMAND_OPEN;
+
 /* Only used in control client mode */
 volatile sig_atomic_t control_client_terminate = 0;
 u_int control_server_pid = 0;
@@ -236,7 +239,7 @@ main(int ac, char **av)
 
 again:
        while ((opt = getopt(ac, av,
-           "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNPR:S:TVXY")) != -1) {
+           "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVXY")) != -1) {
                switch (opt) {
                case '1':
                        options.protocol = SSH_PROTO_1;
@@ -270,6 +273,14 @@ again:
                case 'g':
                        options.gateway_ports = 1;
                        break;
+               case 'O':
+                       if (strcmp(optarg, "check") == 0)
+                               mux_command = SSHMUX_COMMAND_ALIVE_CHECK;
+                       else if (strcmp(optarg, "exit") == 0)
+                               mux_command = SSHMUX_COMMAND_TERMINATE;
+                       else
+                               fatal("Invalid multiplex command.");
+                       break;
                case 'P':       /* deprecated */
                        options.use_privileged_port = 0;
                        break;
@@ -1251,8 +1262,9 @@ control_client(const char *path)
        struct sockaddr_un addr;
        int i, r, fd, sock, exitval, num_env, addr_len;
        Buffer m;
-       char *cp;
+       char *term;
        extern char **environ;
+       u_int  flags;
 
        if (stdin_null_flag) {
                if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
@@ -1278,26 +1290,52 @@ control_client(const char *path)
        if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1)
                fatal("Couldn't connect to %s: %s", path, strerror(errno));
 
-       if ((cp = getenv("TERM")) == NULL)
-               cp = "";
+       if ((term = getenv("TERM")) == NULL)
+               term = "";
+
+       flags = 0;
+       if (tty_flag)
+               flags |= SSHMUX_FLAG_TTY;
+       if (subsystem_flag)
+               flags |= SSHMUX_FLAG_SUBSYS;
 
        buffer_init(&m);
 
-       /* Get PID of controlee */
+       /* Send our command to server */
+       buffer_put_int(&m, mux_command);
+       buffer_put_int(&m, flags);
+       if (ssh_msg_send(sock, /* version */1, &m) == -1)
+               fatal("%s: msg_send", __func__);
+       buffer_clear(&m);
+
+       /* Get authorisation status and PID of controlee */
        if (ssh_msg_recv(sock, &m) == -1)
                fatal("%s: msg_recv", __func__);
-       if (buffer_get_char(&m) != 0)
+       if (buffer_get_char(&m) != 1)
                fatal("%s: wrong version", __func__);
-       /* Connection allowed? */
        if (buffer_get_int(&m) != 1)
                fatal("Connection to master denied");
        control_server_pid = buffer_get_int(&m);
 
        buffer_clear(&m);
-       buffer_put_int(&m, tty_flag);
-       buffer_put_int(&m, subsystem_flag);
-       buffer_put_cstring(&m, cp);
 
+       switch (mux_command) {
+       case SSHMUX_COMMAND_ALIVE_CHECK:
+               fprintf(stderr, "Master running (pid=%d)\r\n", 
+                   control_server_pid);
+               exit(0);
+       case SSHMUX_COMMAND_TERMINATE:
+               fprintf(stderr, "Exit request sent.\r\n");
+               exit(0);
+       case SSHMUX_COMMAND_OPEN:
+               /* continue below */
+               break;
+       default:
+               fatal("silly mux_command %d", mux_command);
+       }
+
+       /* SSHMUX_COMMAND_OPEN */
+       buffer_put_cstring(&m, term);
        buffer_append(&command, "\0", 1);
        buffer_put_cstring(&m, buffer_ptr(&command));
 
@@ -1319,7 +1357,7 @@ control_client(const char *path)
                        }
        }
 
-       if (ssh_msg_send(sock, /* version */0, &m) == -1)
+       if (ssh_msg_send(sock, /* version */1, &m) == -1)
                fatal("%s: msg_send", __func__);
 
        mm_send_fd(sock, STDIN_FILENO);
@@ -1330,8 +1368,8 @@ control_client(const char *path)
        buffer_clear(&m);
        if (ssh_msg_recv(sock, &m) == -1)
                fatal("%s: msg_recv", __func__);
-       if (buffer_get_char(&m) != 0)
-               fatal("%s: master returned error", __func__);
+       if (buffer_get_char(&m) != 1)
+               fatal("%s: wrong version", __func__);
        buffer_free(&m);
 
        signal(SIGHUP, control_client_sighandler);
This page took 0.073401 seconds and 5 git commands to generate.