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

Collapse All | Expand All

(-)a/channels.c (-19 / +51 lines)
Lines 300-305 channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, Link Here
300
    int extusage, int nonblock, int is_tty)
300
    int extusage, int nonblock, int is_tty)
301
{
301
{
302
	struct ssh_channels *sc = ssh->chanctxt;
302
	struct ssh_channels *sc = ssh->chanctxt;
303
	int nb;
303
304
304
	/* Update the maximum file descriptor value. */
305
	/* Update the maximum file descriptor value. */
305
	sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd);
306
	sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd);
Lines 323-329 channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, Link Here
323
		debug2("channel %d: rfd %d isatty", c->self, c->rfd);
324
		debug2("channel %d: rfd %d isatty", c->self, c->rfd);
324
325
325
	/* enable nonblocking mode */
326
	/* enable nonblocking mode */
326
	if (nonblock) {
327
	c->restore_block = 0;
328
	if (nonblock == CHANNEL_NONBLOCK_STDIO) {
329
		/*
330
		 * Special handling for stdio file descriptors: do not set
331
		 * non-blocking mode if they are TTYs. Otherwise prepare to
332
		 * restore their blocking state on exit to avoid interfering
333
		 * with other programs that follow.
334
		 */
335
		if (rfd != -1 && !isatty(rfd) &&
336
		    (nb = fcntl(rfd, F_GETFL)) == 0) {
337
			c->restore_block |= 1;
338
			set_nonblock(rfd);
339
		}
340
		if (wfd != -1 && !isatty(wfd) &&
341
		    (nb = fcntl(wfd, F_GETFL)) != -1) {
342
			c->restore_block |= 1<<1;
343
			set_nonblock(wfd);
344
		}
345
		if (efd != -1 && !isatty(efd) &&
346
		    (nb = fcntl(efd, F_GETFL)) != -1) {
347
			c->restore_block |= 1<<2;
348
			set_nonblock(efd);
349
		}
350
	} else if (nonblock) {
327
		if (rfd != -1)
351
		if (rfd != -1)
328
			set_nonblock(rfd);
352
			set_nonblock(rfd);
329
		if (wfd != -1)
353
		if (wfd != -1)
Lines 378-383 channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, Link Here
378
		fatal_fr(r, "sshbuf_set_max_size");
402
		fatal_fr(r, "sshbuf_set_max_size");
379
	c->ostate = CHAN_OUTPUT_OPEN;
403
	c->ostate = CHAN_OUTPUT_OPEN;
380
	c->istate = CHAN_INPUT_OPEN;
404
	c->istate = CHAN_INPUT_OPEN;
405
	c->restore_block = 0;
381
	channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0);
406
	channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0);
382
	c->self = found;
407
	c->self = found;
383
	c->type = type;
408
	c->type = type;
Lines 412-428 channel_find_maxfd(struct ssh_channels *sc) Link Here
412
}
437
}
413
438
414
int
439
int
415
channel_close_fd(struct ssh *ssh, int *fdp)
440
channel_close_fd(struct ssh *ssh, Channel *c, int *fdp)
416
{
441
{
417
	struct ssh_channels *sc = ssh->chanctxt;
442
	struct ssh_channels *sc = ssh->chanctxt;
418
	int ret = 0, fd = *fdp;
443
	int ret, fd = *fdp;
419
444
420
	if (fd != -1) {
445
	if (fd == -1)
421
		ret = close(fd);
446
		return 0;
422
		*fdp = -1;
447
423
		if (fd == sc->channel_max_fd)
448
	if ((*fdp == c->rfd && (c->restore_block & 1) != 0) ||
424
			channel_find_maxfd(sc);
449
	   (*fdp == c->wfd && (c->restore_block & (1<<1)) != 0) ||
425
	}
450
	   (*fdp == c->efd && (c->restore_block & (1<<2)) != 0))
451
		(void)fcntl(*fdp, F_SETFL, 0);	/* restore blocking */
452
453
	ret = close(fd);
454
	*fdp = -1;
455
	if (fd == sc->channel_max_fd)
456
		channel_find_maxfd(sc);
426
	return ret;
457
	return ret;
427
}
458
}
428
459
Lines 432-444 channel_close_fds(struct ssh *ssh, Channel *c) Link Here
432
{
463
{
433
	int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd;
464
	int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd;
434
465
435
	channel_close_fd(ssh, &c->sock);
466
	channel_close_fd(ssh, c, &c->sock);
436
	if (rfd != sock)
467
	if (rfd != sock)
437
		channel_close_fd(ssh, &c->rfd);
468
		channel_close_fd(ssh, c, &c->rfd);
438
	if (wfd != sock && wfd != rfd)
469
	if (wfd != sock && wfd != rfd)
439
		channel_close_fd(ssh, &c->wfd);
470
		channel_close_fd(ssh, c, &c->wfd);
440
	if (efd != sock && efd != rfd && efd != wfd)
471
	if (efd != sock && efd != rfd && efd != wfd)
441
		channel_close_fd(ssh, &c->efd);
472
		channel_close_fd(ssh, c, &c->efd);
442
}
473
}
443
474
444
static void
475
static void
Lines 692-698 channel_stop_listening(struct ssh *ssh) Link Here
692
			case SSH_CHANNEL_X11_LISTENER:
723
			case SSH_CHANNEL_X11_LISTENER:
693
			case SSH_CHANNEL_UNIX_LISTENER:
724
			case SSH_CHANNEL_UNIX_LISTENER:
694
			case SSH_CHANNEL_RUNIX_LISTENER:
725
			case SSH_CHANNEL_RUNIX_LISTENER:
695
				channel_close_fd(ssh, &c->sock);
726
				channel_close_fd(ssh, c, &c->sock);
696
				channel_free(ssh, c);
727
				channel_free(ssh, c);
697
				break;
728
				break;
698
			}
729
			}
Lines 1481-1487 channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output) Link Here
1481
1512
1482
Channel *
1513
Channel *
1483
channel_connect_stdio_fwd(struct ssh *ssh,
1514
channel_connect_stdio_fwd(struct ssh *ssh,
1484
    const char *host_to_connect, u_short port_to_connect, int in, int out)
1515
    const char *host_to_connect, u_short port_to_connect,
1516
    int in, int out, int nonblock)
1485
{
1517
{
1486
	Channel *c;
1518
	Channel *c;
1487
1519
Lines 1489-1495 channel_connect_stdio_fwd(struct ssh *ssh, Link Here
1489
1521
1490
	c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out,
1522
	c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out,
1491
	    -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
1523
	    -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
1492
	    0, "stdio-forward", /*nonblock*/0);
1524
	    0, "stdio-forward", nonblock);
1493
1525
1494
	c->path = xstrdup(host_to_connect);
1526
	c->path = xstrdup(host_to_connect);
1495
	c->host_port = port_to_connect;
1527
	c->host_port = port_to_connect;
Lines 1639-1645 channel_post_x11_listener(struct ssh *ssh, Channel *c, Link Here
1639
	if (c->single_connection) {
1671
	if (c->single_connection) {
1640
		oerrno = errno;
1672
		oerrno = errno;
1641
		debug2("single_connection: closing X11 listener.");
1673
		debug2("single_connection: closing X11 listener.");
1642
		channel_close_fd(ssh, &c->sock);
1674
		channel_close_fd(ssh, c, &c->sock);
1643
		chan_mark_dead(ssh, c);
1675
		chan_mark_dead(ssh, c);
1644
		errno = oerrno;
1676
		errno = oerrno;
1645
	}
1677
	}
Lines 2028-2034 channel_handle_efd_write(struct ssh *ssh, Channel *c, Link Here
2028
		return 1;
2060
		return 1;
2029
	if (len <= 0) {
2061
	if (len <= 0) {
2030
		debug2("channel %d: closing write-efd %d", c->self, c->efd);
2062
		debug2("channel %d: closing write-efd %d", c->self, c->efd);
2031
		channel_close_fd(ssh, &c->efd);
2063
		channel_close_fd(ssh, c, &c->efd);
2032
	} else {
2064
	} else {
2033
		if ((r = sshbuf_consume(c->extended, len)) != 0)
2065
		if ((r = sshbuf_consume(c->extended, len)) != 0)
2034
			fatal_fr(r, "channel %i: consume", c->self);
2066
			fatal_fr(r, "channel %i: consume", c->self);
Lines 2054-2060 channel_handle_efd_read(struct ssh *ssh, Channel *c, Link Here
2054
		return 1;
2086
		return 1;
2055
	if (len <= 0) {
2087
	if (len <= 0) {
2056
		debug2("channel %d: closing read-efd %d", c->self, c->efd);
2088
		debug2("channel %d: closing read-efd %d", c->self, c->efd);
2057
		channel_close_fd(ssh, &c->efd);
2089
		channel_close_fd(ssh, c, &c->efd);
2058
	} else if (c->extended_usage == CHAN_EXTENDED_IGNORE)
2090
	} else if (c->extended_usage == CHAN_EXTENDED_IGNORE)
2059
		debug3("channel %d: discard efd", c->self);
2091
		debug3("channel %d: discard efd", c->self);
2060
	else if ((r = sshbuf_put(c->extended, buf, len)) != 0)
2092
	else if ((r = sshbuf_put(c->extended, buf, len)) != 0)
(-)a/channels.h (-2 / +8 lines)
Lines 63-68 Link Here
63
63
64
#define CHANNEL_CANCEL_PORT_STATIC	-1
64
#define CHANNEL_CANCEL_PORT_STATIC	-1
65
65
66
/* nonblocking flags for channel_new */
67
#define CHANNEL_NONBLOCK_LEAVE	0 /* don't modify non-blocking state */
68
#define CHANNEL_NONBLOCK_SET	1 /* set non-blocking state */
69
#define CHANNEL_NONBLOCK_STDIO	2 /* set non-blocking and restore on close */
70
66
/* TCP forwarding */
71
/* TCP forwarding */
67
#define FORWARD_DENY		0
72
#define FORWARD_DENY		0
68
#define FORWARD_REMOTE		(1)
73
#define FORWARD_REMOTE		(1)
Lines 136-141 struct Channel { Link Here
136
				 * to a matching pre-select handler.
141
				 * to a matching pre-select handler.
137
				 * this way post-select handlers are not
142
				 * this way post-select handlers are not
138
				 * accidentally called if a FD gets reused */
143
				 * accidentally called if a FD gets reused */
144
	int	restore_block;	/* fd mask to restore blocking status */
139
	struct sshbuf *input;	/* data read from socket, to be sent over
145
	struct sshbuf *input;	/* data read from socket, to be sent over
140
				 * encrypted connection */
146
				 * encrypted connection */
141
	struct sshbuf *output;	/* data received over encrypted connection for
147
	struct sshbuf *output;	/* data received over encrypted connection for
Lines 263-269 void channel_register_filter(struct ssh *, int, channel_infilter_fn *, Link Here
263
void	 channel_register_status_confirm(struct ssh *, int,
269
void	 channel_register_status_confirm(struct ssh *, int,
264
	    channel_confirm_cb *, channel_confirm_abandon_cb *, void *);
270
	    channel_confirm_cb *, channel_confirm_abandon_cb *, void *);
265
void	 channel_cancel_cleanup(struct ssh *, int);
271
void	 channel_cancel_cleanup(struct ssh *, int);
266
int	 channel_close_fd(struct ssh *, int *);
272
int	 channel_close_fd(struct ssh *, Channel *, int *);
267
void	 channel_send_window_changes(struct ssh *);
273
void	 channel_send_window_changes(struct ssh *);
268
274
269
/* mux proxy support */
275
/* mux proxy support */
Lines 310-316 Channel *channel_connect_to_port(struct ssh *, const char *, u_short, Link Here
310
	    char *, char *, int *, const char **);
316
	    char *, char *, int *, const char **);
311
Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
317
Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
312
Channel	*channel_connect_stdio_fwd(struct ssh *, const char*,
318
Channel	*channel_connect_stdio_fwd(struct ssh *, const char*,
313
	    u_short, int, int);
319
	    u_short, int, int, int);
314
Channel	*channel_connect_by_listen_address(struct ssh *, const char *,
320
Channel	*channel_connect_by_listen_address(struct ssh *, const char *,
315
	    u_short, char *, char *);
321
	    u_short, char *, char *);
316
Channel	*channel_connect_by_listen_path(struct ssh *, const char *,
322
Channel	*channel_connect_by_listen_path(struct ssh *, const char *,
(-)a/clientloop.c (-8 lines)
Lines 1397-1410 client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, Link Here
1397
	if (have_pty)
1397
	if (have_pty)
1398
		leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1398
		leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1399
1399
1400
	/* restore blocking io */
1401
	if (!isatty(fileno(stdin)))
1402
		unset_nonblock(fileno(stdin));
1403
	if (!isatty(fileno(stdout)))
1404
		unset_nonblock(fileno(stdout));
1405
	if (!isatty(fileno(stderr)))
1406
		unset_nonblock(fileno(stderr));
1407
1408
	/*
1400
	/*
1409
	 * If there was no shell or command requested, there will be no remote
1401
	 * If there was no shell or command requested, there will be no remote
1410
	 * exit status to be returned.  In that case, clear error code if the
1402
	 * exit status to be returned.  In that case, clear error code if the
(-)a/mux.c (-16 / +3 lines)
Lines 439-452 mux_master_process_new_session(struct ssh *ssh, u_int rid, Link Here
439
	if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
439
	if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
440
		error_f("tcgetattr: %s", strerror(errno));
440
		error_f("tcgetattr: %s", strerror(errno));
441
441
442
	/* enable nonblocking unless tty */
443
	if (!isatty(new_fd[0]))
444
		set_nonblock(new_fd[0]);
445
	if (!isatty(new_fd[1]))
446
		set_nonblock(new_fd[1]);
447
	if (!isatty(new_fd[2]))
448
		set_nonblock(new_fd[2]);
449
450
	window = CHAN_SES_WINDOW_DEFAULT;
442
	window = CHAN_SES_WINDOW_DEFAULT;
451
	packetmax = CHAN_SES_PACKET_DEFAULT;
443
	packetmax = CHAN_SES_PACKET_DEFAULT;
452
	if (cctx->want_tty) {
444
	if (cctx->want_tty) {
Lines 456-462 mux_master_process_new_session(struct ssh *ssh, u_int rid, Link Here
456
448
457
	nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
449
	nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
458
	    new_fd[0], new_fd[1], new_fd[2], window, packetmax,
450
	    new_fd[0], new_fd[1], new_fd[2], window, packetmax,
459
	    CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
451
	    CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO);
460
452
461
	nc->ctl_chan = c->self;		/* link session -> control channel */
453
	nc->ctl_chan = c->self;		/* link session -> control channel */
462
	c->remote_id = nc->self;	/* link control -> session channel */
454
	c->remote_id = nc->self;	/* link control -> session channel */
Lines 1012-1024 mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid, Link Here
1012
		}
1004
		}
1013
	}
1005
	}
1014
1006
1015
	/* enable nonblocking unless tty */
1007
	nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1],
1016
	if (!isatty(new_fd[0]))
1008
	    CHANNEL_NONBLOCK_STDIO);
1017
		set_nonblock(new_fd[0]);
1018
	if (!isatty(new_fd[1]))
1019
		set_nonblock(new_fd[1]);
1020
1021
	nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
1022
	free(chost);
1009
	free(chost);
1023
1010
1024
	nc->ctl_chan = c->self;		/* link session -> control channel */
1011
	nc->ctl_chan = c->self;		/* link session -> control channel */
(-)a/nchan.c (-3 / +3 lines)
Lines 382-388 chan_shutdown_write(struct ssh *ssh, Channel *c) Link Here
382
			    c->istate, c->ostate, strerror(errno));
382
			    c->istate, c->ostate, strerror(errno));
383
		}
383
		}
384
	} else {
384
	} else {
385
		if (channel_close_fd(ssh, &c->wfd) < 0) {
385
		if (channel_close_fd(ssh, c, &c->wfd) < 0) {
386
			logit_f("channel %d: close() failed for "
386
			logit_f("channel %d: close() failed for "
387
			    "fd %d [i%d o%d]: %.100s", c->self, c->wfd,
387
			    "fd %d [i%d o%d]: %.100s", c->self, c->wfd,
388
			    c->istate, c->ostate, strerror(errno));
388
			    c->istate, c->ostate, strerror(errno));
Lines 405-411 chan_shutdown_read(struct ssh *ssh, Channel *c) Link Here
405
			    c->istate, c->ostate, strerror(errno));
405
			    c->istate, c->ostate, strerror(errno));
406
		}
406
		}
407
	} else {
407
	} else {
408
		if (channel_close_fd(ssh, &c->rfd) < 0) {
408
		if (channel_close_fd(ssh, c, &c->rfd) < 0) {
409
			logit_f("channel %d: close() failed for "
409
			logit_f("channel %d: close() failed for "
410
			    "fd %d [i%d o%d]: %.100s", c->self, c->rfd,
410
			    "fd %d [i%d o%d]: %.100s", c->self, c->rfd,
411
			    c->istate, c->ostate, strerror(errno));
411
			    c->istate, c->ostate, strerror(errno));
Lines 424-430 chan_shutdown_extended_read(struct ssh *ssh, Channel *c) Link Here
424
	debug_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
424
	debug_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
425
	    c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd,
425
	    c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd,
426
	    channel_format_extended_usage(c));
426
	    channel_format_extended_usage(c));
427
	if (channel_close_fd(ssh, &c->efd) < 0) {
427
	if (channel_close_fd(ssh, c, &c->efd) < 0) {
428
		logit_f("channel %d: close() failed for "
428
		logit_f("channel %d: close() failed for "
429
		    "extended fd %d [i%d o%d]: %.100s", c->self, c->efd,
429
		    "extended fd %d [i%d o%d]: %.100s", c->self, c->efd,
430
		    c->istate, c->ostate, strerror(errno));
430
		    c->istate, c->ostate, strerror(errno));
(-)a/ssh.c (-11 / +4 lines)
Lines 1855-1863 ssh_init_stdio_forwarding(struct ssh *ssh) Link Here
1855
1855
1856
	if ((in = dup(STDIN_FILENO)) == -1 ||
1856
	if ((in = dup(STDIN_FILENO)) == -1 ||
1857
	    (out = dup(STDOUT_FILENO)) == -1)
1857
	    (out = dup(STDOUT_FILENO)) == -1)
1858
		fatal("channel_connect_stdio_fwd: dup() in/out failed");
1858
		fatal_f("dup() in/out failed");
1859
	if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host,
1859
	if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host,
1860
	    options.stdio_forward_port, in, out)) == NULL)
1860
	    options.stdio_forward_port, in, out,
1861
	    CHANNEL_NONBLOCK_STDIO)) == NULL)
1861
		fatal_f("channel_connect_stdio_fwd failed");
1862
		fatal_f("channel_connect_stdio_fwd failed");
1862
	channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0);
1863
	channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0);
1863
	channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
1864
	channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
Lines 2053-2066 ssh_session2_open(struct ssh *ssh) Link Here
2053
	if (in == -1 || out == -1 || err == -1)
2054
	if (in == -1 || out == -1 || err == -1)
2054
		fatal("dup() in/out/err failed");
2055
		fatal("dup() in/out/err failed");
2055
2056
2056
	/* enable nonblocking unless tty */
2057
	if (!isatty(in))
2058
		set_nonblock(in);
2059
	if (!isatty(out))
2060
		set_nonblock(out);
2061
	if (!isatty(err))
2062
		set_nonblock(err);
2063
2064
	window = CHAN_SES_WINDOW_DEFAULT;
2057
	window = CHAN_SES_WINDOW_DEFAULT;
2065
	packetmax = CHAN_SES_PACKET_DEFAULT;
2058
	packetmax = CHAN_SES_PACKET_DEFAULT;
2066
	if (tty_flag) {
2059
	if (tty_flag) {
Lines 2070-2076 ssh_session2_open(struct ssh *ssh) Link Here
2070
	c = channel_new(ssh,
2063
	c = channel_new(ssh,
2071
	    "session", SSH_CHANNEL_OPENING, in, out, err,
2064
	    "session", SSH_CHANNEL_OPENING, in, out, err,
2072
	    window, packetmax, CHAN_EXTENDED_WRITE,
2065
	    window, packetmax, CHAN_EXTENDED_WRITE,
2073
	    "client-session", /*nonblock*/0);
2066
	    "client-session", CHANNEL_NONBLOCK_STDIO);
2074
2067
2075
	debug3_f("channel_new: %d", c->self);
2068
	debug3_f("channel_new: %d", c->self);
2076
2069

Return to bug 3280