View | Details | Raw Unified | Return to bug 1424 | Differences between
and this patch

Collapse All | Expand All

(-)a/channels.c (+17 lines)
Lines 184-189 channel_by_id(int id) Link Here
184
	return c;
184
	return c;
185
}
185
}
186
186
187
/* Iterate over channels */
188
Channel *
189
channel_next(Channel *current)
190
{
191
	int id = (current ? current->self + 1 : 0);
192
	for (; id < channels_alloc; id++) {
193
		Channel *c = channels[id];
194
		if (c) return c;
195
	}
196
	return NULL;
197
}
198
187
/*
199
/*
188
 * Returns the channel if it is allowed to receive protocol messages.
200
 * Returns the channel if it is allowed to receive protocol messages.
189
 * Private channels, like listening sockets, may not receive messages.
201
 * Private channels, like listening sockets, may not receive messages.
Lines 317-322 channel_new(char *ctype, int type, int rfd, int wfd, int efd, Link Here
317
	c->output_filter = NULL;
329
	c->output_filter = NULL;
318
	c->filter_ctx = NULL;
330
	c->filter_ctx = NULL;
319
	c->filter_cleanup = NULL;
331
	c->filter_cleanup = NULL;
332
	c->tag = NULL;
320
	TAILQ_INIT(&c->status_confirms);
333
	TAILQ_INIT(&c->status_confirms);
321
	debug("channel %d: new [%s]", found, remote_name);
334
	debug("channel %d: new [%s]", found, remote_name);
322
	return c;
335
	return c;
Lines 402-407 channel_free(Channel *c) Link Here
402
		xfree(c->path);
415
		xfree(c->path);
403
		c->path = NULL;
416
		c->path = NULL;
404
	}
417
	}
418
	if (c->tag) {
419
		xfree(c->tag);
420
		c->tag = NULL;
421
	}
405
	while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
422
	while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
406
		if (cc->abandon_cb != NULL)
423
		if (cc->abandon_cb != NULL)
407
			cc->abandon_cb(c, cc->ctx);
424
			cc->abandon_cb(c, cc->ctx);
(-)a/channels.h (+4 lines)
Lines 137-142 struct Channel { Link Here
137
137
138
	/* non-blocking connect */
138
	/* non-blocking connect */
139
	struct channel_connect	connect_ctx;
139
	struct channel_connect	connect_ctx;
140
141
	/* friendly name */
142
	char *tag;
140
};
143
};
141
144
142
#define CHAN_EXTENDED_IGNORE		0
145
#define CHAN_EXTENDED_IGNORE		0
Lines 183-188 struct Channel { Link Here
183
/* channel management */
186
/* channel management */
184
187
185
Channel	*channel_by_id(int);
188
Channel	*channel_by_id(int);
189
Channel *channel_next(Channel *);
186
Channel	*channel_lookup(int);
190
Channel	*channel_lookup(int);
187
Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int);
191
Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int);
188
void	 channel_set_fds(int, int, int, int, int, int, int, u_int);
192
void	 channel_set_fds(int, int, int, int, int, int, int, u_int);
(-)a/clientloop.h (-2 / +4 lines)
Lines 56-67 typedef void global_confirm_cb(int, u_int32_t seq, void *); Link Here
56
void	 client_register_global_confirm(global_confirm_cb *, void *);
56
void	 client_register_global_confirm(global_confirm_cb *, void *);
57
57
58
/* Multiplexing protocol version */
58
/* Multiplexing protocol version */
59
#define SSHMUX_VER			2
59
#define SSHMUX_VER			3
60
60
61
/* Multiplexing control protocol flags */
61
/* Multiplexing control protocol flags */
62
#define SSHMUX_COMMAND_OPEN		1	/* Open new connection */
62
#define SSHMUX_COMMAND_OPEN		1	/* Open new connection */
63
#define SSHMUX_COMMAND_ALIVE_CHECK	2	/* Check master is alive */
63
#define SSHMUX_COMMAND_ALIVE_CHECK	2	/* Check master is alive */
64
#define SSHMUX_COMMAND_TERMINATE	3	/* Ask master to exit */
64
#define SSHMUX_COMMAND_TERMINATE	3	/* Ask master to exit */
65
#define SSHMUX_COMMAND_PS               4       /* Get list of slaves */
66
#define SSHMUX_COMMAND_KILL             5       /* Send signal to remote process */
65
67
66
#define SSHMUX_FLAG_TTY			(1)	/* Request tty on open */
68
#define SSHMUX_FLAG_TTY			(1)	/* Request tty on open */
67
#define SSHMUX_FLAG_SUBSYS		(1<<1)	/* Subsystem request on open */
69
#define SSHMUX_FLAG_SUBSYS		(1<<1)	/* Subsystem request on open */
Lines 70-73 void client_register_global_confirm(global_confirm_cb *, void *); Link Here
70
72
71
void	muxserver_listen(void);
73
void	muxserver_listen(void);
72
int	muxserver_accept_control(void);
74
int	muxserver_accept_control(void);
73
void	muxclient(const char *);
75
void	muxclient(const char *, int ac, char **av);
(-)a/mux.c (-47 / +121 lines)
Lines 67-72 Link Here
67
#include "sshpty.h"
67
#include "sshpty.h"
68
#include "key.h"
68
#include "key.h"
69
#include "readconf.h"
69
#include "readconf.h"
70
#include "compat.h"
70
#include "clientloop.h"
71
#include "clientloop.h"
71
72
72
/* from ssh.c */
73
/* from ssh.c */
Lines 208-218 muxserver_accept_control(void) Link Here
208
{
209
{
209
	Buffer m;
210
	Buffer m;
210
	Channel *c;
211
	Channel *c;
211
	int client_fd, new_fd[3], ver, allowed, window, packetmax;
212
	int client_fd, new_fd[3], ver, allowed, window, packetmax, count;
212
	socklen_t addrlen;
213
	socklen_t addrlen;
213
	struct sockaddr_storage addr;
214
	struct sockaddr_storage addr;
214
	struct mux_session_confirm_ctx *cctx;
215
	struct mux_session_confirm_ctx *cctx;
215
	char *cmd;
216
	char *cmd, *tag, *question, *signal;
216
	u_int i, j, len, env_len, mux_command, flags, escape_char;
217
	u_int i, j, len, env_len, mux_command, flags, escape_char;
217
	uid_t euid;
218
	uid_t euid;
218
	gid_t egid;
219
	gid_t egid;
Lines 260-325 muxserver_accept_control(void) Link Here
260
	}
261
	}
261
262
262
	allowed = 1;
263
	allowed = 1;
264
	question = NULL;
263
	mux_command = buffer_get_int(&m);
265
	mux_command = buffer_get_int(&m);
264
	flags = buffer_get_int(&m);
266
	flags = buffer_get_int(&m);
265
267
268
	/* Process extra arguments and ask user for permission */
269
	switch (mux_command) {
270
	case SSHMUX_COMMAND_OPEN:
271
		question = "Allow shared connection to %s? ";
272
		break;
273
	case SSHMUX_COMMAND_TERMINATE:
274
		question = "Terminate shared connection to %s? ";
275
		break;
276
	case SSHMUX_COMMAND_KILL:
277
		signal = buffer_get_string(&m, &len);
278
		tag = buffer_get_string(&m, &len);
279
		c = NULL;
280
		if (tag && signal && compat20) {
281
			/* channel lookup by tag */
282
			while (c = channel_next(c)) {
283
				if (c->tag && (strcmp(tag, c->tag) == 0))
284
					break;
285
			}
286
			if (c) {
287
			    question = "Send signal to process in %s? ";
288
			    break;
289
			}
290
		}
291
		allowed = 0;
292
		break;
293
	}
294
295
	if (question && (options.control_master == SSHCTL_MASTER_ASK ||
296
			 options.control_master == SSHCTL_MASTER_AUTO_ASK))
297
		allowed = ask_permission(question, host);
298
299
        /* response header */
266
	buffer_clear(&m);
300
	buffer_clear(&m);
301
	buffer_put_int(&m, allowed);
302
	buffer_put_int(&m, getpid());
267
303
268
	switch (mux_command) {
304
	switch (mux_command) {
269
	case SSHMUX_COMMAND_OPEN:
305
	case SSHMUX_COMMAND_OPEN:
270
		if (options.control_master == SSHCTL_MASTER_ASK ||
306
	case SSHMUX_COMMAND_ALIVE_CHECK:
271
		    options.control_master == SSHCTL_MASTER_AUTO_ASK)
272
			allowed = ask_permission("Allow shared connection "
273
			    "to %s? ", host);
274
		/* continue below */
275
		break;
307
		break;
308
276
	case SSHMUX_COMMAND_TERMINATE:
309
	case SSHMUX_COMMAND_TERMINATE:
277
		if (options.control_master == SSHCTL_MASTER_ASK ||
278
		    options.control_master == SSHCTL_MASTER_AUTO_ASK)
279
			allowed = ask_permission("Terminate shared connection "
280
			    "to %s? ", host);
281
		if (allowed)
310
		if (allowed)
282
			start_close = 1;
311
			start_close = 1;
283
		/* FALLTHROUGH */
312
		break;
284
	case SSHMUX_COMMAND_ALIVE_CHECK:
313
285
		/* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
314
	case SSHMUX_COMMAND_PS:
286
		buffer_clear(&m);
315
		count = 0;
287
		buffer_put_int(&m, allowed);
316
		c = NULL;
288
		buffer_put_int(&m, getpid());
317
		while (c = channel_next(c))
289
		if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
318
			if (c->tag)
290
			error("%s: client msg_send failed", __func__);
319
				count ++;
291
			close(client_fd);
320
		buffer_put_int(&m, count);
292
			buffer_free(&m);
321
293
			return start_close;
322
		while (c = channel_next(c))
323
			if (c->tag)
324
				buffer_put_cstring(&m, c->tag);
325
		break;
326
327
	case SSHMUX_COMMAND_KILL:
328
		if (allowed) {
329
			int id = c->self;
330
			channel_request_start(id, "signal", 0);
331
			packet_put_cstring(signal);
332
			packet_send();
294
		}
333
		}
295
		buffer_free(&m);
334
		break;
296
		close(client_fd);
297
		return start_close;
298
	default:
335
	default:
299
		error("Unsupported command %d", mux_command);
336
		error("Unsupported command %d", mux_command);
300
		buffer_free(&m);
337
		goto cleanup;
301
		close(client_fd);
302
		return 0;
303
	}
338
	}
304
339
	if (!allowed)
305
	/* Reply for SSHMUX_COMMAND_OPEN */
340
		error("Refused control connection");
306
	buffer_clear(&m);
307
	buffer_put_int(&m, allowed);
308
	buffer_put_int(&m, getpid());
309
	if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
341
	if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
310
		error("%s: client msg_send failed", __func__);
342
		error("%s: client msg_send failed", __func__);
311
		close(client_fd);
343
		goto cleanup;
312
		buffer_free(&m);
313
		return 0;
314
	}
344
	}
315
345
316
	if (!allowed) {
346
	if ((mux_command != SSHMUX_COMMAND_OPEN) || !allowed) {
317
		error("Refused control connection");
347
	cleanup:
318
		close(client_fd);
319
		buffer_free(&m);
348
		buffer_free(&m);
320
		return 0;
349
		close(client_fd);
350
		return start_close;
321
	}
351
	}
322
352
353
	/* Continue SSHMUX_COMMAND_OPEN processing */
354
323
	buffer_clear(&m);
355
	buffer_clear(&m);
324
	if (ssh_msg_recv(client_fd, &m) == -1) {
356
	if (ssh_msg_recv(client_fd, &m) == -1) {
325
		error("%s: client msg_recv failed", __func__);
357
		error("%s: client msg_recv failed", __func__);
Lines 341-346 muxserver_accept_control(void) Link Here
341
	cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
373
	cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
342
	cctx->term = buffer_get_string(&m, &len);
374
	cctx->term = buffer_get_string(&m, &len);
343
	escape_char = buffer_get_int(&m);
375
	escape_char = buffer_get_int(&m);
376
	tag = buffer_get_string(&m, &len);
344
377
345
	cmd = buffer_get_string(&m, &len);
378
	cmd = buffer_get_string(&m, &len);
346
	buffer_init(&cctx->cmd);
379
	buffer_init(&cctx->cmd);
Lines 375-380 muxserver_accept_control(void) Link Here
375
			buffer_free(&cctx->cmd);
408
			buffer_free(&cctx->cmd);
376
			close(client_fd);
409
			close(client_fd);
377
			xfree(cctx);
410
			xfree(cctx);
411
			xfree(tag);
378
			return 0;
412
			return 0;
379
		}
413
		}
380
	}
414
	}
Lines 401-406 muxserver_accept_control(void) Link Here
401
				xfree(cctx->env[i]);
435
				xfree(cctx->env[i]);
402
			xfree(cctx->env);
436
			xfree(cctx->env);
403
		}
437
		}
438
		xfree(cctx);
439
		xfree(tag);
404
		return 0;
440
		return 0;
405
	}
441
	}
406
	buffer_free(&m);
442
	buffer_free(&m);
Lines 427-432 muxserver_accept_control(void) Link Here
427
	    CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
463
	    CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
428
464
429
	c->ctl_fd = client_fd;
465
	c->ctl_fd = client_fd;
466
	c->tag = tag;
430
	if (cctx->want_tty && escape_char != 0xffffffff) {
467
	if (cctx->want_tty && escape_char != 0xffffffff) {
431
		channel_register_filter(c->self,
468
		channel_register_filter(c->self,
432
		    client_simple_escape_filter, NULL,
469
		    client_simple_escape_filter, NULL,
Lines 487-503 env_permitted(char *env) Link Here
487
524
488
/* Multiplex client main loop. */
525
/* Multiplex client main loop. */
489
void
526
void
490
muxclient(const char *path)
527
muxclient(const char *path, int ac, char **av)
491
{
528
{
492
	struct sockaddr_un addr;
529
	struct sockaddr_un addr;
493
	int i, r, fd, sock, exitval[2], num_env;
530
	int i, r, fd, sock, exitval[2], num_env, count, len;
494
	Buffer m;
531
	Buffer m;
495
	char *term;
532
	char *term, *tag = NULL;
496
	extern char **environ;
533
	extern char **environ;
497
	u_int allowed, flags;
534
	u_int allowed, flags;
498
535
499
	if (muxclient_command == 0)
536
	switch (muxclient_command) {
537
	case 0:
500
		muxclient_command = SSHMUX_COMMAND_OPEN;
538
		muxclient_command = SSHMUX_COMMAND_OPEN;
539
		break;
540
	case SSHMUX_COMMAND_KILL:
541
		if (ac != 2)
542
			fatal("Bad number of arguments for kill command");
543
		break;
544
	}
501
545
502
	switch (options.control_master) {
546
	switch (options.control_master) {
503
	case SSHCTL_MASTER_AUTO:
547
	case SSHCTL_MASTER_AUTO:
Lines 562-570 muxclient(const char *path) Link Here
562
606
563
	buffer_init(&m);
607
	buffer_init(&m);
564
608
565
	/* Send our command to server */
609
	/* Build command header */
566
	buffer_put_int(&m, muxclient_command);
610
	buffer_put_int(&m, muxclient_command);
567
	buffer_put_int(&m, flags);
611
	buffer_put_int(&m, flags);
612
613
	/* Add command specific data */
614
	switch (muxclient_command) {
615
	case SSHMUX_COMMAND_KILL:
616
		buffer_put_cstring(&m, av[0]);
617
		buffer_put_cstring(&m, av[1]);
618
		break;
619
	}
620
621
	/* Send our command to server */
568
	if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) {
622
	if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) {
569
		error("%s: msg_send", __func__);
623
		error("%s: msg_send", __func__);
570
 muxerr:
624
 muxerr:
Lines 599-606 muxclient(const char *path) Link Here
599
	}
653
	}
600
	muxserver_pid = buffer_get_int(&m);
654
	muxserver_pid = buffer_get_int(&m);
601
655
602
	buffer_clear(&m);
603
604
	switch (muxclient_command) {
656
	switch (muxclient_command) {
605
	case SSHMUX_COMMAND_ALIVE_CHECK:
657
	case SSHMUX_COMMAND_ALIVE_CHECK:
606
		fprintf(stderr, "Master running (pid=%d)\r\n",
658
		fprintf(stderr, "Master running (pid=%d)\r\n",
Lines 609-620 muxclient(const char *path) Link Here
609
	case SSHMUX_COMMAND_TERMINATE:
661
	case SSHMUX_COMMAND_TERMINATE:
610
		fprintf(stderr, "Exit request sent.\r\n");
662
		fprintf(stderr, "Exit request sent.\r\n");
611
		exit(0);
663
		exit(0);
664
	case SSHMUX_COMMAND_KILL:
665
		fprintf(stderr, "Signal request sent.\r\n");
666
		exit(0);
667
	case SSHMUX_COMMAND_PS:
668
		if (buffer_get_int_ret(&count, &m) != 0) {
669
			error("%s: bad server reply", __func__);
670
			goto muxerr;
671
		}
672
		for (i = 0; i < count; i++) {
673
			char *tag = buffer_get_string(&m, &len);
674
			if (!tag) {
675
				error("%s: bad server reply", __func__);
676
				goto muxerr;
677
			}
678
			printf("%s\n", tag);
679
			xfree(tag);
680
		}
681
		exit(0);
682
612
	case SSHMUX_COMMAND_OPEN:
683
	case SSHMUX_COMMAND_OPEN:
684
		buffer_clear(&m);
613
		buffer_put_cstring(&m, term ? term : "");
685
		buffer_put_cstring(&m, term ? term : "");
614
		if (options.escape_char == SSH_ESCAPECHAR_NONE)
686
		if (options.escape_char == SSH_ESCAPECHAR_NONE)
615
			buffer_put_int(&m, 0xffffffff);
687
			buffer_put_int(&m, 0xffffffff);
616
		else
688
		else
617
			buffer_put_int(&m, options.escape_char);
689
			buffer_put_int(&m, options.escape_char);
690
		xasprintf(&tag, "%ld", (long)getpid());
691
		buffer_put_cstring(&m, tag);
618
		buffer_append(&command, "\0", 1);
692
		buffer_append(&command, "\0", 1);
619
		buffer_put_cstring(&m, buffer_ptr(&command));
693
		buffer_put_cstring(&m, buffer_ptr(&command));
620
694
(-)a/session.c (+5 lines)
Lines 1838-1843 session_env_req(Session *s) Link Here
1838
static int
1838
static int
1839
name2sig(char *name)
1839
name2sig(char *name)
1840
{
1840
{
1841
	char *end;
1842
	int sig;
1841
#define SSH_SIG(x) if (strcmp(name, #x) == 0) return SIG ## x
1843
#define SSH_SIG(x) if (strcmp(name, #x) == 0) return SIG ## x
1842
	SSH_SIG(ABRT);
1844
	SSH_SIG(ABRT);
1843
	SSH_SIG(ALRM);
1845
	SSH_SIG(ALRM);
Lines 1853-1858 name2sig(char *name) Link Here
1853
	SSH_SIG(USR1);
1855
	SSH_SIG(USR1);
1854
	SSH_SIG(USR2);
1856
	SSH_SIG(USR2);
1855
#undef	SSH_SIG
1857
#undef	SSH_SIG
1858
	sig = strtol(name, &end, 10);
1859
	if (*end == '\0' && end != name)
1860
		return sig;
1856
	return -1;
1861
	return -1;
1857
}
1862
}
1858
1863
(-)a/ssh.c (-2 / +7 lines)
Lines 187-193 static int ssh_session2(void); Link Here
187
static void load_public_identity_files(void);
187
static void load_public_identity_files(void);
188
188
189
/* from muxclient.c */
189
/* from muxclient.c */
190
void muxclient(const char *);
190
void muxclient(const char *, int ac, char **av);
191
void muxserver_listen(void);
191
void muxserver_listen(void);
192
192
193
/*
193
/*
Lines 304-309 main(int ac, char **av) Link Here
304
				muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
304
				muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
305
			else if (strcmp(optarg, "exit") == 0)
305
			else if (strcmp(optarg, "exit") == 0)
306
				muxclient_command = SSHMUX_COMMAND_TERMINATE;
306
				muxclient_command = SSHMUX_COMMAND_TERMINATE;
307
			else if (strcmp(optarg, "ps") == 0)
308
				muxclient_command = SSHMUX_COMMAND_PS;
309
			else if (strcmp(optarg, "kill") == 0)
310
				muxclient_command = SSHMUX_COMMAND_KILL;
307
			else
311
			else
308
				fatal("Invalid multiplex command.");
312
				fatal("Invalid multiplex command.");
309
			break;
313
			break;
Lines 682-688 main(int ac, char **av) Link Here
682
	if (muxclient_command != 0 && options.control_path == NULL)
686
	if (muxclient_command != 0 && options.control_path == NULL)
683
		fatal("No ControlPath specified for \"-O\" command");
687
		fatal("No ControlPath specified for \"-O\" command");
684
	if (options.control_path != NULL)
688
	if (options.control_path != NULL)
685
		muxclient(options.control_path);
689
		muxclient(options.control_path, ac, av);
686
690
687
	timeout_ms = options.connection_timeout * 1000;
691
	timeout_ms = options.connection_timeout * 1000;
688
692
Lines 1156-1161 ssh_session2_open(void) Link Here
1156
	    "session", SSH_CHANNEL_OPENING, in, out, err,
1160
	    "session", SSH_CHANNEL_OPENING, in, out, err,
1157
	    window, packetmax, CHAN_EXTENDED_WRITE,
1161
	    window, packetmax, CHAN_EXTENDED_WRITE,
1158
	    "client-session", /*nonblock*/0);
1162
	    "client-session", /*nonblock*/0);
1163
	xasprintf(&c->tag, "%ld", (long)getpid());
1159
1164
1160
	debug3("ssh_session2_open: channel_new: %d", c->self);
1165
	debug3("ssh_session2_open: channel_new: %d", c->self);
1161
1166

Return to bug 1424