summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-08-23 22:56:08 +0100
committerColin Watson <cjwatson@debian.org>2010-08-23 22:56:08 +0100
commit31e30b835fd9695d3b6647cab4867001b092e28f (patch)
tree138e715c25661825457c7280cd66e3f4853d474c /clientloop.c
parent78eedc2c60ff4718200f9271d8ee4f437da3a0c5 (diff)
parent43094ebf14c9b16f1ea398bc5b65a7335e947288 (diff)
merge 5.6p1
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c89
1 files changed, 79 insertions, 10 deletions
diff --git a/clientloop.c b/clientloop.c
index cbbb3df1f..ef97859f1 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.219 2010/03/13 21:10:38 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.222 2010/07/19 09:15:12 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -149,6 +149,9 @@ static volatile sig_atomic_t received_signal = 0;
149/* Flag indicating whether the user's terminal is in non-blocking mode. */ 149/* Flag indicating whether the user's terminal is in non-blocking mode. */
150static int in_non_blocking_mode = 0; 150static int in_non_blocking_mode = 0;
151 151
152/* Time when backgrounded control master using ControlPersist should exit */
153static time_t control_persist_exit_time = 0;
154
152/* Common data for the client loop code. */ 155/* Common data for the client loop code. */
153volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ 156volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
154static int escape_char1; /* Escape character. (proto1 only) */ 157static int escape_char1; /* Escape character. (proto1 only) */
@@ -159,11 +162,12 @@ static int stdin_eof; /* EOF has been encountered on stderr. */
159static Buffer stdin_buffer; /* Buffer for stdin data. */ 162static Buffer stdin_buffer; /* Buffer for stdin data. */
160static Buffer stdout_buffer; /* Buffer for stdout data. */ 163static Buffer stdout_buffer; /* Buffer for stdout data. */
161static Buffer stderr_buffer; /* Buffer for stderr data. */ 164static Buffer stderr_buffer; /* Buffer for stderr data. */
162static u_int buffer_high;/* Soft max buffer size. */ 165static u_int buffer_high; /* Soft max buffer size. */
163static int connection_in; /* Connection to server (input). */ 166static int connection_in; /* Connection to server (input). */
164static int connection_out; /* Connection to server (output). */ 167static int connection_out; /* Connection to server (output). */
165static int need_rekeying; /* Set to non-zero if rekeying is requested. */ 168static int need_rekeying; /* Set to non-zero if rekeying is requested. */
166static int session_closed = 0; /* In SSH2: login session closed. */ 169static int session_closed; /* In SSH2: login session closed. */
170static int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
167 171
168static void client_init_dispatch(void); 172static void client_init_dispatch(void);
169int session_ident = -1; 173int session_ident = -1;
@@ -255,10 +259,38 @@ get_current_time(void)
255 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; 259 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
256} 260}
257 261
262/*
263 * Sets control_persist_exit_time to the absolute time when the
264 * backgrounded control master should exit due to expiry of the
265 * ControlPersist timeout. Sets it to 0 if we are not a backgrounded
266 * control master process, or if there is no ControlPersist timeout.
267 */
268static void
269set_control_persist_exit_time(void)
270{
271 if (muxserver_sock == -1 || !options.control_persist
272 || options.control_persist_timeout == 0)
273 /* not using a ControlPersist timeout */
274 control_persist_exit_time = 0;
275 else if (channel_still_open()) {
276 /* some client connections are still open */
277 if (control_persist_exit_time > 0)
278 debug2("%s: cancel scheduled exit", __func__);
279 control_persist_exit_time = 0;
280 } else if (control_persist_exit_time <= 0) {
281 /* a client connection has recently closed */
282 control_persist_exit_time = time(NULL) +
283 (time_t)options.control_persist_timeout;
284 debug2("%s: schedule exit in %d seconds", __func__,
285 options.control_persist_timeout);
286 }
287 /* else we are already counting down to the timeout */
288}
289
258#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" 290#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
259void 291void
260client_x11_get_proto(const char *display, const char *xauth_path, 292client_x11_get_proto(const char *display, const char *xauth_path,
261 u_int trusted, char **_proto, char **_data) 293 u_int trusted, u_int timeout, char **_proto, char **_data)
262{ 294{
263 char cmd[1024]; 295 char cmd[1024];
264 char line[512]; 296 char line[512];
@@ -268,6 +300,7 @@ client_x11_get_proto(const char *display, const char *xauth_path,
268 int got_data = 0, generated = 0, do_unlink = 0, i; 300 int got_data = 0, generated = 0, do_unlink = 0, i;
269 char *xauthdir, *xauthfile; 301 char *xauthdir, *xauthfile;
270 struct stat st; 302 struct stat st;
303 u_int now;
271 304
272 xauthdir = xauthfile = NULL; 305 xauthdir = xauthfile = NULL;
273 *_proto = proto; 306 *_proto = proto;
@@ -303,11 +336,18 @@ client_x11_get_proto(const char *display, const char *xauth_path,
303 xauthdir); 336 xauthdir);
304 snprintf(cmd, sizeof(cmd), 337 snprintf(cmd, sizeof(cmd),
305 "%s -f %s generate %s " SSH_X11_PROTO 338 "%s -f %s generate %s " SSH_X11_PROTO
306 " untrusted timeout 1200 2>" _PATH_DEVNULL, 339 " untrusted timeout %u 2>" _PATH_DEVNULL,
307 xauth_path, xauthfile, display); 340 xauth_path, xauthfile, display, timeout);
308 debug2("x11_get_proto: %s", cmd); 341 debug2("x11_get_proto: %s", cmd);
309 if (system(cmd) == 0) 342 if (system(cmd) == 0)
310 generated = 1; 343 generated = 1;
344 if (x11_refuse_time == 0) {
345 now = time(NULL) + 1;
346 if (UINT_MAX - timeout < now)
347 x11_refuse_time = UINT_MAX;
348 else
349 x11_refuse_time = now + timeout;
350 }
311 } 351 }
312 } 352 }
313 353
@@ -528,6 +568,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
528 int *maxfdp, u_int *nallocp, int rekeying) 568 int *maxfdp, u_int *nallocp, int rekeying)
529{ 569{
530 struct timeval tv, *tvp; 570 struct timeval tv, *tvp;
571 int timeout_secs;
531 int ret; 572 int ret;
532 573
533 /* Add any selections by the channel mechanism. */ 574 /* Add any selections by the channel mechanism. */
@@ -571,16 +612,27 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
571 /* 612 /*
572 * Wait for something to happen. This will suspend the process until 613 * Wait for something to happen. This will suspend the process until
573 * some selected descriptor can be read, written, or has some other 614 * some selected descriptor can be read, written, or has some other
574 * event pending. 615 * event pending, or a timeout expires.
575 */ 616 */
576 617
577 if (options.server_alive_interval == 0 || !compat20) 618 timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
619 if (options.server_alive_interval > 0 && compat20)
620 timeout_secs = options.server_alive_interval;
621 set_control_persist_exit_time();
622 if (control_persist_exit_time > 0) {
623 timeout_secs = MIN(timeout_secs,
624 control_persist_exit_time - time(NULL));
625 if (timeout_secs < 0)
626 timeout_secs = 0;
627 }
628 if (timeout_secs == INT_MAX)
578 tvp = NULL; 629 tvp = NULL;
579 else { 630 else {
580 tv.tv_sec = options.server_alive_interval; 631 tv.tv_sec = timeout_secs;
581 tv.tv_usec = 0; 632 tv.tv_usec = 0;
582 tvp = &tv; 633 tvp = &tv;
583 } 634 }
635
584 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); 636 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
585 if (ret < 0) { 637 if (ret < 0) {
586 char buf[100]; 638 char buf[100];
@@ -1482,6 +1534,18 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1482 */ 1534 */
1483 if (FD_ISSET(connection_out, writeset)) 1535 if (FD_ISSET(connection_out, writeset))
1484 packet_write_poll(); 1536 packet_write_poll();
1537
1538 /*
1539 * If we are a backgrounded control master, and the
1540 * timeout has expired without any active client
1541 * connections, then quit.
1542 */
1543 if (control_persist_exit_time > 0) {
1544 if (time(NULL) >= control_persist_exit_time) {
1545 debug("ControlPersist timeout expired");
1546 break;
1547 }
1548 }
1485 } 1549 }
1486 if (readset) 1550 if (readset)
1487 xfree(readset); 1551 xfree(readset);
@@ -1699,6 +1763,11 @@ client_request_x11(const char *request_type, int rchan)
1699 "malicious server."); 1763 "malicious server.");
1700 return NULL; 1764 return NULL;
1701 } 1765 }
1766 if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) {
1767 verbose("Rejected X11 connection after ForwardX11Timeout "
1768 "expired");
1769 return NULL;
1770 }
1702 originator = packet_get_string(NULL); 1771 originator = packet_get_string(NULL);
1703 if (datafellows & SSH_BUG_X11FWD) { 1772 if (datafellows & SSH_BUG_X11FWD) {
1704 debug2("buggy server: x11 request w/o originator_port"); 1773 debug2("buggy server: x11 request w/o originator_port");
@@ -1925,7 +1994,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
1925 memset(&ws, 0, sizeof(ws)); 1994 memset(&ws, 0, sizeof(ws));
1926 1995
1927 channel_request_start(id, "pty-req", 1); 1996 channel_request_start(id, "pty-req", 1);
1928 client_expect_confirm(id, "PTY allocation", 0); 1997 client_expect_confirm(id, "PTY allocation", 1);
1929 packet_put_cstring(term != NULL ? term : ""); 1998 packet_put_cstring(term != NULL ? term : "");
1930 packet_put_int((u_int)ws.ws_col); 1999 packet_put_int((u_int)ws.ws_col);
1931 packet_put_int((u_int)ws.ws_row); 2000 packet_put_int((u_int)ws.ws_row);