diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 89 |
1 files changed, 79 insertions, 10 deletions
diff --git a/clientloop.c b/clientloop.c index 05e7de067..337f47c09 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. */ |
150 | static int in_non_blocking_mode = 0; | 150 | static int in_non_blocking_mode = 0; |
151 | 151 | ||
152 | /* Time when backgrounded control master using ControlPersist should exit */ | ||
153 | static time_t control_persist_exit_time = 0; | ||
154 | |||
152 | /* Common data for the client loop code. */ | 155 | /* Common data for the client loop code. */ |
153 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ | 156 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
154 | static int escape_char1; /* Escape character. (proto1 only) */ | 157 | static int escape_char1; /* Escape character. (proto1 only) */ |
@@ -159,11 +162,12 @@ static int stdin_eof; /* EOF has been encountered on stderr. */ | |||
159 | static Buffer stdin_buffer; /* Buffer for stdin data. */ | 162 | static Buffer stdin_buffer; /* Buffer for stdin data. */ |
160 | static Buffer stdout_buffer; /* Buffer for stdout data. */ | 163 | static Buffer stdout_buffer; /* Buffer for stdout data. */ |
161 | static Buffer stderr_buffer; /* Buffer for stderr data. */ | 164 | static Buffer stderr_buffer; /* Buffer for stderr data. */ |
162 | static u_int buffer_high;/* Soft max buffer size. */ | 165 | static u_int buffer_high; /* Soft max buffer size. */ |
163 | static int connection_in; /* Connection to server (input). */ | 166 | static int connection_in; /* Connection to server (input). */ |
164 | static int connection_out; /* Connection to server (output). */ | 167 | static int connection_out; /* Connection to server (output). */ |
165 | static int need_rekeying; /* Set to non-zero if rekeying is requested. */ | 168 | static int need_rekeying; /* Set to non-zero if rekeying is requested. */ |
166 | static int session_closed = 0; /* In SSH2: login session closed. */ | 169 | static int session_closed; /* In SSH2: login session closed. */ |
170 | static int x11_refuse_time; /* If >0, refuse x11 opens after this time. */ | ||
167 | 171 | ||
168 | static void client_init_dispatch(void); | 172 | static void client_init_dispatch(void); |
169 | int session_ident = -1; | 173 | int 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 | */ | ||
268 | static void | ||
269 | set_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" |
259 | void | 291 | void |
260 | client_x11_get_proto(const char *display, const char *xauth_path, | 292 | client_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 | ||
@@ -533,6 +573,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
533 | int *maxfdp, u_int *nallocp, int rekeying) | 573 | int *maxfdp, u_int *nallocp, int rekeying) |
534 | { | 574 | { |
535 | struct timeval tv, *tvp; | 575 | struct timeval tv, *tvp; |
576 | int timeout_secs; | ||
536 | int ret; | 577 | int ret; |
537 | 578 | ||
538 | /* Add any selections by the channel mechanism. */ | 579 | /* Add any selections by the channel mechanism. */ |
@@ -576,16 +617,27 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
576 | /* | 617 | /* |
577 | * Wait for something to happen. This will suspend the process until | 618 | * Wait for something to happen. This will suspend the process until |
578 | * some selected descriptor can be read, written, or has some other | 619 | * some selected descriptor can be read, written, or has some other |
579 | * event pending. | 620 | * event pending, or a timeout expires. |
580 | */ | 621 | */ |
581 | 622 | ||
582 | if (options.server_alive_interval == 0) | 623 | timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ |
624 | if (options.server_alive_interval > 0) | ||
625 | timeout_secs = options.server_alive_interval; | ||
626 | set_control_persist_exit_time(); | ||
627 | if (control_persist_exit_time > 0) { | ||
628 | timeout_secs = MIN(timeout_secs, | ||
629 | control_persist_exit_time - time(NULL)); | ||
630 | if (timeout_secs < 0) | ||
631 | timeout_secs = 0; | ||
632 | } | ||
633 | if (timeout_secs == INT_MAX) | ||
583 | tvp = NULL; | 634 | tvp = NULL; |
584 | else { | 635 | else { |
585 | tv.tv_sec = options.server_alive_interval; | 636 | tv.tv_sec = timeout_secs; |
586 | tv.tv_usec = 0; | 637 | tv.tv_usec = 0; |
587 | tvp = &tv; | 638 | tvp = &tv; |
588 | } | 639 | } |
640 | |||
589 | ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); | 641 | ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); |
590 | if (ret < 0) { | 642 | if (ret < 0) { |
591 | char buf[100]; | 643 | char buf[100]; |
@@ -1487,6 +1539,18 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1487 | */ | 1539 | */ |
1488 | if (FD_ISSET(connection_out, writeset)) | 1540 | if (FD_ISSET(connection_out, writeset)) |
1489 | packet_write_poll(); | 1541 | packet_write_poll(); |
1542 | |||
1543 | /* | ||
1544 | * If we are a backgrounded control master, and the | ||
1545 | * timeout has expired without any active client | ||
1546 | * connections, then quit. | ||
1547 | */ | ||
1548 | if (control_persist_exit_time > 0) { | ||
1549 | if (time(NULL) >= control_persist_exit_time) { | ||
1550 | debug("ControlPersist timeout expired"); | ||
1551 | break; | ||
1552 | } | ||
1553 | } | ||
1490 | } | 1554 | } |
1491 | if (readset) | 1555 | if (readset) |
1492 | xfree(readset); | 1556 | xfree(readset); |
@@ -1706,6 +1770,11 @@ client_request_x11(const char *request_type, int rchan) | |||
1706 | "malicious server."); | 1770 | "malicious server."); |
1707 | return NULL; | 1771 | return NULL; |
1708 | } | 1772 | } |
1773 | if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) { | ||
1774 | verbose("Rejected X11 connection after ForwardX11Timeout " | ||
1775 | "expired"); | ||
1776 | return NULL; | ||
1777 | } | ||
1709 | originator = packet_get_string(NULL); | 1778 | originator = packet_get_string(NULL); |
1710 | if (datafellows & SSH_BUG_X11FWD) { | 1779 | if (datafellows & SSH_BUG_X11FWD) { |
1711 | debug2("buggy server: x11 request w/o originator_port"); | 1780 | debug2("buggy server: x11 request w/o originator_port"); |
@@ -1932,7 +2001,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
1932 | memset(&ws, 0, sizeof(ws)); | 2001 | memset(&ws, 0, sizeof(ws)); |
1933 | 2002 | ||
1934 | channel_request_start(id, "pty-req", 1); | 2003 | channel_request_start(id, "pty-req", 1); |
1935 | client_expect_confirm(id, "PTY allocation", 0); | 2004 | client_expect_confirm(id, "PTY allocation", 1); |
1936 | packet_put_cstring(term != NULL ? term : ""); | 2005 | packet_put_cstring(term != NULL ? term : ""); |
1937 | packet_put_int((u_int)ws.ws_col); | 2006 | packet_put_int((u_int)ws.ws_col); |
1938 | packet_put_int((u_int)ws.ws_row); | 2007 | packet_put_int((u_int)ws.ws_row); |