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 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. */ |
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 | ||
@@ -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); |