summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c195
1 files changed, 116 insertions, 79 deletions
diff --git a/clientloop.c b/clientloop.c
index 5653cc489..3b6cacb08 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.275 2015/07/10 06:21:53 markus Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.284 2016/02/08 10:57:07 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
@@ -111,7 +111,6 @@
111#include "sshpty.h" 111#include "sshpty.h"
112#include "match.h" 112#include "match.h"
113#include "msg.h" 113#include "msg.h"
114#include "roaming.h"
115#include "ssherr.h" 114#include "ssherr.h"
116#include "hostfile.h" 115#include "hostfile.h"
117 116
@@ -173,8 +172,6 @@ static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
173static void client_init_dispatch(void); 172static void client_init_dispatch(void);
174int session_ident = -1; 173int session_ident = -1;
175 174
176int session_resumed = 0;
177
178/* Track escape per proto2 channel */ 175/* Track escape per proto2 channel */
179struct escape_filter_ctx { 176struct escape_filter_ctx {
180 int escape_pending; 177 int escape_pending;
@@ -292,6 +289,9 @@ client_x11_display_valid(const char *display)
292{ 289{
293 size_t i, dlen; 290 size_t i, dlen;
294 291
292 if (display == NULL)
293 return 0;
294
295 dlen = strlen(display); 295 dlen = strlen(display);
296 for (i = 0; i < dlen; i++) { 296 for (i = 0; i < dlen; i++) {
297 if (!isalnum((u_char)display[i]) && 297 if (!isalnum((u_char)display[i]) &&
@@ -305,35 +305,34 @@ client_x11_display_valid(const char *display)
305 305
306#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" 306#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
307#define X11_TIMEOUT_SLACK 60 307#define X11_TIMEOUT_SLACK 60
308void 308int
309client_x11_get_proto(const char *display, const char *xauth_path, 309client_x11_get_proto(const char *display, const char *xauth_path,
310 u_int trusted, u_int timeout, char **_proto, char **_data) 310 u_int trusted, u_int timeout, char **_proto, char **_data)
311{ 311{
312 char cmd[1024]; 312 char cmd[1024], line[512], xdisplay[512];
313 char line[512]; 313 char xauthfile[PATH_MAX], xauthdir[PATH_MAX];
314 char xdisplay[512];
315 static char proto[512], data[512]; 314 static char proto[512], data[512];
316 FILE *f; 315 FILE *f;
317 int got_data = 0, generated = 0, do_unlink = 0, i; 316 int got_data = 0, generated = 0, do_unlink = 0, i, r;
318 char *xauthdir, *xauthfile;
319 struct stat st; 317 struct stat st;
320 u_int now, x11_timeout_real; 318 u_int now, x11_timeout_real;
321 319
322 xauthdir = xauthfile = NULL;
323 *_proto = proto; 320 *_proto = proto;
324 *_data = data; 321 *_data = data;
325 proto[0] = data[0] = '\0'; 322 proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0';
326 323
327 if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) { 324 if (!client_x11_display_valid(display)) {
325 if (display != NULL)
326 logit("DISPLAY \"%s\" invalid; disabling X11 forwarding",
327 display);
328 return -1;
329 }
330 if (xauth_path != NULL && stat(xauth_path, &st) == -1) {
328 debug("No xauth program."); 331 debug("No xauth program.");
329 } else if (!client_x11_display_valid(display)) { 332 xauth_path = NULL;
330 logit("DISPLAY '%s' invalid, falling back to fake xauth data", 333 }
331 display); 334
332 } else { 335 if (xauth_path != NULL) {
333 if (display == NULL) {
334 debug("x11_get_proto: DISPLAY not set");
335 return;
336 }
337 /* 336 /*
338 * Handle FamilyLocal case where $DISPLAY does 337 * Handle FamilyLocal case where $DISPLAY does
339 * not match an authorization entry. For this we 338 * not match an authorization entry. For this we
@@ -342,45 +341,60 @@ client_x11_get_proto(const char *display, const char *xauth_path,
342 * is not perfect. 341 * is not perfect.
343 */ 342 */
344 if (strncmp(display, "localhost:", 10) == 0) { 343 if (strncmp(display, "localhost:", 10) == 0) {
345 snprintf(xdisplay, sizeof(xdisplay), "unix:%s", 344 if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
346 display + 10); 345 display + 10)) < 0 ||
346 (size_t)r >= sizeof(xdisplay)) {
347 error("%s: display name too long", __func__);
348 return -1;
349 }
347 display = xdisplay; 350 display = xdisplay;
348 } 351 }
349 if (trusted == 0) { 352 if (trusted == 0) {
350 xauthdir = xmalloc(PATH_MAX);
351 xauthfile = xmalloc(PATH_MAX);
352 mktemp_proto(xauthdir, PATH_MAX);
353 /* 353 /*
354 * Generate an untrusted X11 auth cookie.
355 *
354 * The authentication cookie should briefly outlive 356 * The authentication cookie should briefly outlive
355 * ssh's willingness to forward X11 connections to 357 * ssh's willingness to forward X11 connections to
356 * avoid nasty fail-open behaviour in the X server. 358 * avoid nasty fail-open behaviour in the X server.
357 */ 359 */
360 mktemp_proto(xauthdir, sizeof(xauthdir));
361 if (mkdtemp(xauthdir) == NULL) {
362 error("%s: mkdtemp: %s",
363 __func__, strerror(errno));
364 return -1;
365 }
366 do_unlink = 1;
367 if ((r = snprintf(xauthfile, sizeof(xauthfile),
368 "%s/xauthfile", xauthdir)) < 0 ||
369 (size_t)r >= sizeof(xauthfile)) {
370 error("%s: xauthfile path too long", __func__);
371 unlink(xauthfile);
372 rmdir(xauthdir);
373 return -1;
374 }
375
358 if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK) 376 if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK)
359 x11_timeout_real = UINT_MAX; 377 x11_timeout_real = UINT_MAX;
360 else 378 else
361 x11_timeout_real = timeout + X11_TIMEOUT_SLACK; 379 x11_timeout_real = timeout + X11_TIMEOUT_SLACK;
362 if (mkdtemp(xauthdir) != NULL) { 380 if ((r = snprintf(cmd, sizeof(cmd),
363 do_unlink = 1; 381 "%s -f %s generate %s " SSH_X11_PROTO
364 snprintf(xauthfile, PATH_MAX, "%s/xauthfile", 382 " untrusted timeout %u 2>" _PATH_DEVNULL,
365 xauthdir); 383 xauth_path, xauthfile, display,
366 snprintf(cmd, sizeof(cmd), 384 x11_timeout_real)) < 0 ||
367 "%s -f %s generate %s " SSH_X11_PROTO 385 (size_t)r >= sizeof(cmd))
368 " untrusted timeout %u 2>" _PATH_DEVNULL, 386 fatal("%s: cmd too long", __func__);
369 xauth_path, xauthfile, display, 387 debug2("%s: %s", __func__, cmd);
370 x11_timeout_real); 388 if (x11_refuse_time == 0) {
371 debug2("x11_get_proto: %s", cmd); 389 now = monotime() + 1;
372 if (x11_refuse_time == 0) { 390 if (UINT_MAX - timeout < now)
373 now = monotime() + 1; 391 x11_refuse_time = UINT_MAX;
374 if (UINT_MAX - timeout < now) 392 else
375 x11_refuse_time = UINT_MAX; 393 x11_refuse_time = now + timeout;
376 else 394 channel_set_x11_refuse_time(x11_refuse_time);
377 x11_refuse_time = now + timeout;
378 channel_set_x11_refuse_time(
379 x11_refuse_time);
380 }
381 if (system(cmd) == 0)
382 generated = 1;
383 } 395 }
396 if (system(cmd) == 0)
397 generated = 1;
384 } 398 }
385 399
386 /* 400 /*
@@ -402,17 +416,20 @@ client_x11_get_proto(const char *display, const char *xauth_path,
402 got_data = 1; 416 got_data = 1;
403 if (f) 417 if (f)
404 pclose(f); 418 pclose(f);
405 } else 419 }
406 error("Warning: untrusted X11 forwarding setup failed: "
407 "xauth key data not generated");
408 } 420 }
409 421
410 if (do_unlink) { 422 if (do_unlink) {
411 unlink(xauthfile); 423 unlink(xauthfile);
412 rmdir(xauthdir); 424 rmdir(xauthdir);
413 } 425 }
414 free(xauthdir); 426
415 free(xauthfile); 427 /* Don't fall back to fake X11 data for untrusted forwarding */
428 if (!trusted && !got_data) {
429 error("Warning: untrusted X11 forwarding setup failed: "
430 "xauth key data not generated");
431 return -1;
432 }
416 433
417 /* 434 /*
418 * If we didn't get authentication data, just make up some 435 * If we didn't get authentication data, just make up some
@@ -436,6 +453,8 @@ client_x11_get_proto(const char *display, const char *xauth_path,
436 rnd >>= 8; 453 rnd >>= 8;
437 } 454 }
438 } 455 }
456
457 return 0;
439} 458}
440 459
441/* 460/*
@@ -739,7 +758,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
739static void 758static void
740client_process_net_input(fd_set *readset) 759client_process_net_input(fd_set *readset)
741{ 760{
742 int len, cont = 0; 761 int len;
743 char buf[SSH_IOBUFSZ]; 762 char buf[SSH_IOBUFSZ];
744 763
745 /* 764 /*
@@ -748,8 +767,8 @@ client_process_net_input(fd_set *readset)
748 */ 767 */
749 if (FD_ISSET(connection_in, readset)) { 768 if (FD_ISSET(connection_in, readset)) {
750 /* Read as much as possible. */ 769 /* Read as much as possible. */
751 len = roaming_read(connection_in, buf, sizeof(buf), &cont); 770 len = read(connection_in, buf, sizeof(buf));
752 if (len == 0 && cont == 0) { 771 if (len == 0) {
753 /* 772 /*
754 * Received EOF. The remote host has closed the 773 * Received EOF. The remote host has closed the
755 * connection. 774 * connection.
@@ -1487,13 +1506,43 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1487{ 1506{
1488 fd_set *readset = NULL, *writeset = NULL; 1507 fd_set *readset = NULL, *writeset = NULL;
1489 double start_time, total_time; 1508 double start_time, total_time;
1490 int r, max_fd = 0, max_fd2 = 0, len, rekeying = 0; 1509 int r, max_fd = 0, max_fd2 = 0, len;
1491 u_int64_t ibytes, obytes; 1510 u_int64_t ibytes, obytes;
1492 u_int nalloc = 0; 1511 u_int nalloc = 0;
1493 char buf[100]; 1512 char buf[100];
1494 1513
1495 debug("Entering interactive session."); 1514 debug("Entering interactive session.");
1496 1515
1516 if (options.control_master &&
1517 ! option_clear_or_none(options.control_path)) {
1518 debug("pledge: id");
1519 if (pledge("stdio rpath wpath cpath unix inet dns proc exec id tty",
1520 NULL) == -1)
1521 fatal("%s pledge(): %s", __func__, strerror(errno));
1522
1523 } else if (options.forward_x11 || options.permit_local_command) {
1524 debug("pledge: exec");
1525 if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
1526 NULL) == -1)
1527 fatal("%s pledge(): %s", __func__, strerror(errno));
1528
1529 } else if (options.update_hostkeys) {
1530 debug("pledge: filesystem full");
1531 if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
1532 NULL) == -1)
1533 fatal("%s pledge(): %s", __func__, strerror(errno));
1534
1535 } else if (! option_clear_or_none(options.proxy_command)) {
1536 debug("pledge: proc");
1537 if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1)
1538 fatal("%s pledge(): %s", __func__, strerror(errno));
1539
1540 } else {
1541 debug("pledge: network");
1542 if (pledge("stdio unix inet dns tty", NULL) == -1)
1543 fatal("%s pledge(): %s", __func__, strerror(errno));
1544 }
1545
1497 start_time = get_current_time(); 1546 start_time = get_current_time();
1498 1547
1499 /* Initialize variables. */ 1548 /* Initialize variables. */
@@ -1572,10 +1621,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1572 if (compat20 && session_closed && !channel_still_open()) 1621 if (compat20 && session_closed && !channel_still_open())
1573 break; 1622 break;
1574 1623
1575 rekeying = (active_state->kex != NULL && !active_state->kex->done); 1624 if (ssh_packet_is_rekeying(active_state)) {
1576
1577 if (rekeying) {
1578 debug("rekeying in progress"); 1625 debug("rekeying in progress");
1626 } else if (need_rekeying) {
1627 /* manual rekey request */
1628 debug("need rekeying");
1629 if ((r = kex_start_rekex(active_state)) != 0)
1630 fatal("%s: kex_start_rekex: %s", __func__,
1631 ssh_err(r));
1632 need_rekeying = 0;
1579 } else { 1633 } else {
1580 /* 1634 /*
1581 * Make packets of buffered stdin data, and buffer 1635 * Make packets of buffered stdin data, and buffer
@@ -1606,13 +1660,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1606 */ 1660 */
1607 max_fd2 = max_fd; 1661 max_fd2 = max_fd;
1608 client_wait_until_can_do_something(&readset, &writeset, 1662 client_wait_until_can_do_something(&readset, &writeset,
1609 &max_fd2, &nalloc, rekeying); 1663 &max_fd2, &nalloc, ssh_packet_is_rekeying(active_state));
1610 1664
1611 if (quit_pending) 1665 if (quit_pending)
1612 break; 1666 break;
1613 1667
1614 /* Do channel operations unless rekeying in progress. */ 1668 /* Do channel operations unless rekeying in progress. */
1615 if (!rekeying) { 1669 if (!ssh_packet_is_rekeying(active_state)) {
1616 channel_after_select(readset, writeset); 1670 channel_after_select(readset, writeset);
1617 1671
1618#ifdef GSSAPI 1672#ifdef GSSAPI
@@ -1622,15 +1676,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1622 need_rekeying = 1; 1676 need_rekeying = 1;
1623 } 1677 }
1624#endif 1678#endif
1625
1626 if (need_rekeying || packet_need_rekeying()) {
1627 debug("need rekeying");
1628 active_state->kex->done = 0;
1629 if ((r = kex_send_kexinit(active_state)) != 0)
1630 fatal("%s: kex_send_kexinit: %s",
1631 __func__, ssh_err(r));
1632 need_rekeying = 0;
1633 }
1634 } 1679 }
1635 1680
1636 /* Buffer input from the connection. */ 1681 /* Buffer input from the connection. */
@@ -1649,14 +1694,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1649 client_process_output(writeset); 1694 client_process_output(writeset);
1650 } 1695 }
1651 1696
1652 if (session_resumed) {
1653 connection_in = packet_get_connection_in();
1654 connection_out = packet_get_connection_out();
1655 max_fd = MAX(max_fd, connection_out);
1656 max_fd = MAX(max_fd, connection_in);
1657 session_resumed = 0;
1658 }
1659
1660 /* 1697 /*
1661 * Send as much buffered packet data as possible to the 1698 * Send as much buffered packet data as possible to the
1662 * sender. 1699 * sender.
@@ -1752,7 +1789,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1752 } 1789 }
1753 1790
1754 /* Clear and free any buffers. */ 1791 /* Clear and free any buffers. */
1755 memset(buf, 0, sizeof(buf)); 1792 explicit_bzero(buf, sizeof(buf));
1756 buffer_free(&stdin_buffer); 1793 buffer_free(&stdin_buffer);
1757 buffer_free(&stdout_buffer); 1794 buffer_free(&stdout_buffer);
1758 buffer_free(&stderr_buffer); 1795 buffer_free(&stderr_buffer);