summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2004-11-07 20:06:19 +1100
committerDarren Tucker <dtucker@zip.com.au>2004-11-07 20:06:19 +1100
commit7ebfc10884da0e430966cb323f57de17397f64bc (patch)
treecb4ab9a4f8cc8378a2c63ca3d46d2f94a2d5c724
parent2d963d87210c6a0c5eadfa5f02c808f6d983b47e (diff)
- 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@
-rw-r--r--ChangeLog6
-rw-r--r--clientloop.c86
-rw-r--r--clientloop.h10
-rw-r--r--ssh.119
-rw-r--r--ssh.c66
5 files changed, 153 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index 871187478..fe96f8d0c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,10 @@
4 [sftp.c] 4 [sftp.c]
5 command editing and history support via libedit; ok markus@ 5 command editing and history support via libedit; ok markus@
6 thanks to hshoexer@ and many testers on tech@ too 6 thanks to hshoexer@ and many testers on tech@ too
7 - djm@cvs.openbsd.org 2004/11/07 00:01:46
8 [clientloop.c clientloop.h ssh.1 ssh.c]
9 add basic control of a running multiplex master connection; including the
10 ability to check its status and request it to exit; ok markus@
7 11
820041105 1220041105
9 - (dtucker) OpenBSD CVS Sync 13 - (dtucker) OpenBSD CVS Sync
@@ -1848,4 +1852,4 @@
1848 - (djm) Trim deprecated options from INSTALL. Mention UsePAM 1852 - (djm) Trim deprecated options from INSTALL. Mention UsePAM
1849 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu 1853 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
1850 1854
1851$Id: ChangeLog,v 1.3579 2004/11/07 09:04:10 dtucker Exp $ 1855$Id: ChangeLog,v 1.3580 2004/11/07 09:06:19 dtucker Exp $
diff --git a/clientloop.c b/clientloop.c
index d77337b82..033a98a5b 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -59,7 +59,7 @@
59 */ 59 */
60 60
61#include "includes.h" 61#include "includes.h"
62RCSID("$OpenBSD: clientloop.c,v 1.133 2004/10/29 22:53:56 djm Exp $"); 62RCSID("$OpenBSD: clientloop.c,v 1.134 2004/11/07 00:01:46 djm Exp $");
63 63
64#include "ssh.h" 64#include "ssh.h"
65#include "ssh1.h" 65#include "ssh1.h"
@@ -561,7 +561,7 @@ client_process_control(fd_set * readset)
561 struct sockaddr_storage addr; 561 struct sockaddr_storage addr;
562 struct confirm_ctx *cctx; 562 struct confirm_ctx *cctx;
563 char *cmd; 563 char *cmd;
564 u_int len, env_len; 564 u_int len, env_len, command, flags;
565 uid_t euid; 565 uid_t euid;
566 gid_t egid; 566 gid_t egid;
567 567
@@ -591,24 +591,74 @@ client_process_control(fd_set * readset)
591 return; 591 return;
592 } 592 }
593 593
594 allowed = 1;
595 if (options.control_master == 2)
596 allowed = ask_permission("Allow shared connection to %s? ",
597 host);
598
599 unset_nonblock(client_fd); 594 unset_nonblock(client_fd);
600 595
596 /* Read command */
601 buffer_init(&m); 597 buffer_init(&m);
598 if (ssh_msg_recv(client_fd, &m) == -1) {
599 error("%s: client msg_recv failed", __func__);
600 close(client_fd);
601 buffer_free(&m);
602 return;
603 }
604 if ((ver = buffer_get_char(&m)) != 1) {
605 error("%s: wrong client version %d", __func__, ver);
606 buffer_free(&m);
607 close(client_fd);
608 return;
609 }
610
611 allowed = 1;
612 command = buffer_get_int(&m);
613 flags = buffer_get_int(&m);
614
615 buffer_clear(&m);
602 616
617 switch (command) {
618 case SSHMUX_COMMAND_OPEN:
619 if (options.control_master == 2)
620 allowed = ask_permission("Allow shared connection "
621 "to %s? ", host);
622 /* continue below */
623 break;
624 case SSHMUX_COMMAND_TERMINATE:
625 if (options.control_master == 2)
626 allowed = ask_permission("Terminate shared connection "
627 "to %s? ", host);
628 if (allowed)
629 quit_pending = 1;
630 /* FALLTHROUGH */
631 case SSHMUX_COMMAND_ALIVE_CHECK:
632 /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
633 buffer_clear(&m);
634 buffer_put_int(&m, allowed);
635 buffer_put_int(&m, getpid());
636 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
637 error("%s: client msg_send failed", __func__);
638 close(client_fd);
639 buffer_free(&m);
640 return;
641 }
642 buffer_free(&m);
643 close(client_fd);
644 return;
645 default:
646 error("Unsupported command %d", command);
647 buffer_free(&m);
648 close(client_fd);
649 return;
650 }
651
652 /* Reply for SSHMUX_COMMAND_OPEN */
653 buffer_clear(&m);
603 buffer_put_int(&m, allowed); 654 buffer_put_int(&m, allowed);
604 buffer_put_int(&m, getpid()); 655 buffer_put_int(&m, getpid());
605 if (ssh_msg_send(client_fd, /* version */0, &m) == -1) { 656 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
606 error("%s: client msg_send failed", __func__); 657 error("%s: client msg_send failed", __func__);
607 close(client_fd); 658 close(client_fd);
608 buffer_free(&m); 659 buffer_free(&m);
609 return; 660 return;
610 } 661 }
611 buffer_clear(&m);
612 662
613 if (!allowed) { 663 if (!allowed) {
614 error("Refused control connection"); 664 error("Refused control connection");
@@ -617,14 +667,14 @@ client_process_control(fd_set * readset)
617 return; 667 return;
618 } 668 }
619 669
670 buffer_clear(&m);
620 if (ssh_msg_recv(client_fd, &m) == -1) { 671 if (ssh_msg_recv(client_fd, &m) == -1) {
621 error("%s: client msg_recv failed", __func__); 672 error("%s: client msg_recv failed", __func__);
622 close(client_fd); 673 close(client_fd);
623 buffer_free(&m); 674 buffer_free(&m);
624 return; 675 return;
625 } 676 }
626 677 if ((ver = buffer_get_char(&m)) != 1) {
627 if ((ver = buffer_get_char(&m)) != 0) {
628 error("%s: wrong client version %d", __func__, ver); 678 error("%s: wrong client version %d", __func__, ver);
629 buffer_free(&m); 679 buffer_free(&m);
630 close(client_fd); 680 close(client_fd);
@@ -633,9 +683,8 @@ client_process_control(fd_set * readset)
633 683
634 cctx = xmalloc(sizeof(*cctx)); 684 cctx = xmalloc(sizeof(*cctx));
635 memset(cctx, 0, sizeof(*cctx)); 685 memset(cctx, 0, sizeof(*cctx));
636 686 cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
637 cctx->want_tty = buffer_get_int(&m); 687 cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
638 cctx->want_subsys = buffer_get_int(&m);
639 cctx->term = buffer_get_string(&m, &len); 688 cctx->term = buffer_get_string(&m, &len);
640 689
641 cmd = buffer_get_string(&m, &len); 690 cmd = buffer_get_string(&m, &len);
@@ -667,14 +716,21 @@ client_process_control(fd_set * readset)
667 if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1) 716 if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
668 error("%s: tcgetattr: %s", __func__, strerror(errno)); 717 error("%s: tcgetattr: %s", __func__, strerror(errno));
669 718
719 /* This roundtrip is just for synchronisation of ttymodes */
670 buffer_clear(&m); 720 buffer_clear(&m);
671 if (ssh_msg_send(client_fd, /* version */0, &m) == -1) { 721 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
672 error("%s: client msg_send failed", __func__); 722 error("%s: client msg_send failed", __func__);
673 close(client_fd); 723 close(client_fd);
674 close(new_fd[0]); 724 close(new_fd[0]);
675 close(new_fd[1]); 725 close(new_fd[1]);
676 close(new_fd[2]); 726 close(new_fd[2]);
677 buffer_free(&m); 727 buffer_free(&m);
728 xfree(cctx->term);
729 if (env_len != 0) {
730 for (i = 0; i < env_len; i++)
731 xfree(cctx->env[i]);
732 xfree(cctx->env);
733 }
678 return; 734 return;
679 } 735 }
680 buffer_free(&m); 736 buffer_free(&m);
diff --git a/clientloop.h b/clientloop.h
index 9992d5938..b23c111cb 100644
--- a/clientloop.h
+++ b/clientloop.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.h,v 1.11 2004/07/11 17:48:47 deraadt Exp $ */ 1/* $OpenBSD: clientloop.h,v 1.12 2004/11/07 00:01:46 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -40,3 +40,11 @@ int client_loop(int, int, int);
40void client_global_request_reply_fwd(int, u_int32_t, void *); 40void client_global_request_reply_fwd(int, u_int32_t, void *);
41void client_session2_setup(int, int, int, const char *, struct termios *, 41void client_session2_setup(int, int, int, const char *, struct termios *,
42 int, Buffer *, char **, dispatch_fn *); 42 int, Buffer *, char **, dispatch_fn *);
43
44/* Multiplexing control protocol flags */
45#define SSHMUX_COMMAND_OPEN 1 /* Open new connection */
46#define SSHMUX_COMMAND_ALIVE_CHECK 2 /* Check master is alive */
47#define SSHMUX_COMMAND_TERMINATE 3 /* Ask master to exit */
48
49#define SSHMUX_FLAG_TTY (1) /* Request tty on open */
50#define SSHMUX_FLAG_SUBSYS (1<<1) /* Subsystem request on open */
diff --git a/ssh.1 b/ssh.1
index 06cb60cec..ec83319b8 100644
--- a/ssh.1
+++ b/ssh.1
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: ssh.1,v 1.197 2004/10/07 10:10:24 djm Exp $ 37.\" $OpenBSD: ssh.1,v 1.198 2004/11/07 00:01:46 djm Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSH 1 39.Dt SSH 1
40.Os 40.Os
@@ -62,6 +62,7 @@
62.Ek 62.Ek
63.Op Fl l Ar login_name 63.Op Fl l Ar login_name
64.Op Fl m Ar mac_spec 64.Op Fl m Ar mac_spec
65.Op Fl O Ar ctl_cmd
65.Op Fl o Ar option 66.Op Fl o Ar option
66.Bk -words 67.Bk -words
67.Op Fl p Ar port 68.Op Fl p Ar port
@@ -74,7 +75,7 @@
74.Sm on 75.Sm on
75.Xc 76.Xc
76.Oc 77.Oc
77.Op Fl S Ar ctl 78.Op Fl S Ar ctl_path
78.Oo Ar user Ns @ Oc Ns Ar hostname 79.Oo Ar user Ns @ Oc Ns Ar hostname
79.Op Ar command 80.Op Ar command
80.Sh DESCRIPTION 81.Sh DESCRIPTION
@@ -613,6 +614,18 @@ be specified in order of preference.
613See the 614See the
614.Cm MACs 615.Cm MACs
615keyword for more information. 616keyword for more information.
617.It Fl O Ar ctl_cmd
618Control an active connection multiplexing master process.
619When the
620.Fl O
621option is specified, the
622.Ar ctl_cmd
623argument is interpreted and passed to the master process.
624Valid commands are:
625.Dq check
626(check that the master process is running) and
627.Dq exit
628(request the master to exit).
616.It Fl N 629.It Fl N
617Do not execute a remote command. 630Do not execute a remote command.
618This is useful for just forwarding ports 631This is useful for just forwarding ports
@@ -735,7 +748,7 @@ IPv6 addresses can be specified with an alternative syntax:
735.Ar hostport . 748.Ar hostport .
736.Xc 749.Xc
737.Sm on 750.Sm on
738.It Fl S Ar ctl 751.It Fl S Ar ctl_path
739Specifies the location of a control socket for connection sharing. 752Specifies the location of a control socket for connection sharing.
740Refer to the description of 753Refer to the description of
741.Cm ControlPath 754.Cm ControlPath
diff --git a/ssh.c b/ssh.c
index c231c5fae..dfe9b25c1 100644
--- a/ssh.c
+++ b/ssh.c
@@ -40,7 +40,7 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: ssh.c,v 1.228 2004/09/23 13:00:04 djm Exp $"); 43RCSID("$OpenBSD: ssh.c,v 1.229 2004/11/07 00:01:46 djm Exp $");
44 44
45#include <openssl/evp.h> 45#include <openssl/evp.h>
46#include <openssl/err.h> 46#include <openssl/err.h>
@@ -144,6 +144,9 @@ pid_t proxy_command_pid = 0;
144/* fd to control socket */ 144/* fd to control socket */
145int control_fd = -1; 145int control_fd = -1;
146 146
147/* Multiplexing control command */
148static u_int mux_command = SSHMUX_COMMAND_OPEN;
149
147/* Only used in control client mode */ 150/* Only used in control client mode */
148volatile sig_atomic_t control_client_terminate = 0; 151volatile sig_atomic_t control_client_terminate = 0;
149u_int control_server_pid = 0; 152u_int control_server_pid = 0;
@@ -236,7 +239,7 @@ main(int ac, char **av)
236 239
237again: 240again:
238 while ((opt = getopt(ac, av, 241 while ((opt = getopt(ac, av,
239 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNPR:S:TVXY")) != -1) { 242 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVXY")) != -1) {
240 switch (opt) { 243 switch (opt) {
241 case '1': 244 case '1':
242 options.protocol = SSH_PROTO_1; 245 options.protocol = SSH_PROTO_1;
@@ -270,6 +273,14 @@ again:
270 case 'g': 273 case 'g':
271 options.gateway_ports = 1; 274 options.gateway_ports = 1;
272 break; 275 break;
276 case 'O':
277 if (strcmp(optarg, "check") == 0)
278 mux_command = SSHMUX_COMMAND_ALIVE_CHECK;
279 else if (strcmp(optarg, "exit") == 0)
280 mux_command = SSHMUX_COMMAND_TERMINATE;
281 else
282 fatal("Invalid multiplex command.");
283 break;
273 case 'P': /* deprecated */ 284 case 'P': /* deprecated */
274 options.use_privileged_port = 0; 285 options.use_privileged_port = 0;
275 break; 286 break;
@@ -1251,8 +1262,9 @@ control_client(const char *path)
1251 struct sockaddr_un addr; 1262 struct sockaddr_un addr;
1252 int i, r, fd, sock, exitval, num_env, addr_len; 1263 int i, r, fd, sock, exitval, num_env, addr_len;
1253 Buffer m; 1264 Buffer m;
1254 char *cp; 1265 char *term;
1255 extern char **environ; 1266 extern char **environ;
1267 u_int flags;
1256 1268
1257 if (stdin_null_flag) { 1269 if (stdin_null_flag) {
1258 if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1) 1270 if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
@@ -1278,26 +1290,52 @@ control_client(const char *path)
1278 if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1) 1290 if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1)
1279 fatal("Couldn't connect to %s: %s", path, strerror(errno)); 1291 fatal("Couldn't connect to %s: %s", path, strerror(errno));
1280 1292
1281 if ((cp = getenv("TERM")) == NULL) 1293 if ((term = getenv("TERM")) == NULL)
1282 cp = ""; 1294 term = "";
1295
1296 flags = 0;
1297 if (tty_flag)
1298 flags |= SSHMUX_FLAG_TTY;
1299 if (subsystem_flag)
1300 flags |= SSHMUX_FLAG_SUBSYS;
1283 1301
1284 buffer_init(&m); 1302 buffer_init(&m);
1285 1303
1286 /* Get PID of controlee */ 1304 /* Send our command to server */
1305 buffer_put_int(&m, mux_command);
1306 buffer_put_int(&m, flags);
1307 if (ssh_msg_send(sock, /* version */1, &m) == -1)
1308 fatal("%s: msg_send", __func__);
1309 buffer_clear(&m);
1310
1311 /* Get authorisation status and PID of controlee */
1287 if (ssh_msg_recv(sock, &m) == -1) 1312 if (ssh_msg_recv(sock, &m) == -1)
1288 fatal("%s: msg_recv", __func__); 1313 fatal("%s: msg_recv", __func__);
1289 if (buffer_get_char(&m) != 0) 1314 if (buffer_get_char(&m) != 1)
1290 fatal("%s: wrong version", __func__); 1315 fatal("%s: wrong version", __func__);
1291 /* Connection allowed? */
1292 if (buffer_get_int(&m) != 1) 1316 if (buffer_get_int(&m) != 1)
1293 fatal("Connection to master denied"); 1317 fatal("Connection to master denied");
1294 control_server_pid = buffer_get_int(&m); 1318 control_server_pid = buffer_get_int(&m);
1295 1319
1296 buffer_clear(&m); 1320 buffer_clear(&m);
1297 buffer_put_int(&m, tty_flag);
1298 buffer_put_int(&m, subsystem_flag);
1299 buffer_put_cstring(&m, cp);
1300 1321
1322 switch (mux_command) {
1323 case SSHMUX_COMMAND_ALIVE_CHECK:
1324 fprintf(stderr, "Master running (pid=%d)\r\n",
1325 control_server_pid);
1326 exit(0);
1327 case SSHMUX_COMMAND_TERMINATE:
1328 fprintf(stderr, "Exit request sent.\r\n");
1329 exit(0);
1330 case SSHMUX_COMMAND_OPEN:
1331 /* continue below */
1332 break;
1333 default:
1334 fatal("silly mux_command %d", mux_command);
1335 }
1336
1337 /* SSHMUX_COMMAND_OPEN */
1338 buffer_put_cstring(&m, term);
1301 buffer_append(&command, "\0", 1); 1339 buffer_append(&command, "\0", 1);
1302 buffer_put_cstring(&m, buffer_ptr(&command)); 1340 buffer_put_cstring(&m, buffer_ptr(&command));
1303 1341
@@ -1319,7 +1357,7 @@ control_client(const char *path)
1319 } 1357 }
1320 } 1358 }
1321 1359
1322 if (ssh_msg_send(sock, /* version */0, &m) == -1) 1360 if (ssh_msg_send(sock, /* version */1, &m) == -1)
1323 fatal("%s: msg_send", __func__); 1361 fatal("%s: msg_send", __func__);
1324 1362
1325 mm_send_fd(sock, STDIN_FILENO); 1363 mm_send_fd(sock, STDIN_FILENO);
@@ -1330,8 +1368,8 @@ control_client(const char *path)
1330 buffer_clear(&m); 1368 buffer_clear(&m);
1331 if (ssh_msg_recv(sock, &m) == -1) 1369 if (ssh_msg_recv(sock, &m) == -1)
1332 fatal("%s: msg_recv", __func__); 1370 fatal("%s: msg_recv", __func__);
1333 if (buffer_get_char(&m) != 0) 1371 if (buffer_get_char(&m) != 1)
1334 fatal("%s: master returned error", __func__); 1372 fatal("%s: wrong version", __func__);
1335 buffer_free(&m); 1373 buffer_free(&m);
1336 1374
1337 signal(SIGHUP, control_client_sighandler); 1375 signal(SIGHUP, control_client_sighandler);