diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | clientloop.c | 86 | ||||
-rw-r--r-- | clientloop.h | 10 | ||||
-rw-r--r-- | ssh.1 | 19 | ||||
-rw-r--r-- | ssh.c | 66 |
5 files changed, 153 insertions, 34 deletions
@@ -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 | ||
8 | 20041105 | 12 | 20041105 |
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" |
62 | RCSID("$OpenBSD: clientloop.c,v 1.133 2004/10/29 22:53:56 djm Exp $"); | 62 | RCSID("$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); | |||
40 | void client_global_request_reply_fwd(int, u_int32_t, void *); | 40 | void client_global_request_reply_fwd(int, u_int32_t, void *); |
41 | void client_session2_setup(int, int, int, const char *, struct termios *, | 41 | void 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 */ | ||
@@ -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. | |||
613 | See the | 614 | See the |
614 | .Cm MACs | 615 | .Cm MACs |
615 | keyword for more information. | 616 | keyword for more information. |
617 | .It Fl O Ar ctl_cmd | ||
618 | Control an active connection multiplexing master process. | ||
619 | When the | ||
620 | .Fl O | ||
621 | option is specified, the | ||
622 | .Ar ctl_cmd | ||
623 | argument is interpreted and passed to the master process. | ||
624 | Valid 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 |
617 | Do not execute a remote command. | 630 | Do not execute a remote command. |
618 | This is useful for just forwarding ports | 631 | This 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 |
739 | Specifies the location of a control socket for connection sharing. | 752 | Specifies the location of a control socket for connection sharing. |
740 | Refer to the description of | 753 | Refer to the description of |
741 | .Cm ControlPath | 754 | .Cm ControlPath |
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: ssh.c,v 1.228 2004/09/23 13:00:04 djm Exp $"); | 43 | RCSID("$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 */ |
145 | int control_fd = -1; | 145 | int control_fd = -1; |
146 | 146 | ||
147 | /* Multiplexing control command */ | ||
148 | static u_int mux_command = SSHMUX_COMMAND_OPEN; | ||
149 | |||
147 | /* Only used in control client mode */ | 150 | /* Only used in control client mode */ |
148 | volatile sig_atomic_t control_client_terminate = 0; | 151 | volatile sig_atomic_t control_client_terminate = 0; |
149 | u_int control_server_pid = 0; | 152 | u_int control_server_pid = 0; |
@@ -236,7 +239,7 @@ main(int ac, char **av) | |||
236 | 239 | ||
237 | again: | 240 | again: |
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); |