- 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@
This commit is contained in:
parent
2d963d8721
commit
7ebfc10884
|
@ -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
|
||||
|
@ -1848,4 +1852,4 @@
|
|||
- (djm) Trim deprecated options from INSTALL. Mention UsePAM
|
||||
- (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
|
||||
|
||||
$Id: ChangeLog,v 1.3579 2004/11/07 09:04:10 dtucker Exp $
|
||||
$Id: ChangeLog,v 1.3580 2004/11/07 09:06:19 dtucker Exp $
|
||||
|
|
86
clientloop.c
86
clientloop.c
|
@ -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);
|
||||
|
|
10
clientloop.h
10
clientloop.h
|
@ -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 */
|
||||
|
|
19
ssh.1
19
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
|
||||
|
|
66
ssh.c
66
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);
|
||||
|
|
Loading…
Reference in New Issue