summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2016-02-29 12:15:15 +0000
committerColin Watson <cjwatson@debian.org>2016-02-29 12:15:15 +0000
commitc52a95cc4754e6630c96fe65ae0c65eb41d2c590 (patch)
tree793395934013923b7b2426382c0676edcd4be3d4 /clientloop.c
parenteeff4de96f5d7365750dc56912c2c62b5c28db6b (diff)
parent72b061d4ba0f909501c595d709ea76e06b01e5c9 (diff)
Import openssh_7.2p1.orig.tar.gz
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 87ceb3dab..9820455c4 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
@@ -169,8 +168,6 @@ static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
169static void client_init_dispatch(void); 168static void client_init_dispatch(void);
170int session_ident = -1; 169int session_ident = -1;
171 170
172int session_resumed = 0;
173
174/* Track escape per proto2 channel */ 171/* Track escape per proto2 channel */
175struct escape_filter_ctx { 172struct escape_filter_ctx {
176 int escape_pending; 173 int escape_pending;
@@ -288,6 +285,9 @@ client_x11_display_valid(const char *display)
288{ 285{
289 size_t i, dlen; 286 size_t i, dlen;
290 287
288 if (display == NULL)
289 return 0;
290
291 dlen = strlen(display); 291 dlen = strlen(display);
292 for (i = 0; i < dlen; i++) { 292 for (i = 0; i < dlen; i++) {
293 if (!isalnum((u_char)display[i]) && 293 if (!isalnum((u_char)display[i]) &&
@@ -301,35 +301,34 @@ client_x11_display_valid(const char *display)
301 301
302#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" 302#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
303#define X11_TIMEOUT_SLACK 60 303#define X11_TIMEOUT_SLACK 60
304void 304int
305client_x11_get_proto(const char *display, const char *xauth_path, 305client_x11_get_proto(const char *display, const char *xauth_path,
306 u_int trusted, u_int timeout, char **_proto, char **_data) 306 u_int trusted, u_int timeout, char **_proto, char **_data)
307{ 307{
308 char cmd[1024]; 308 char cmd[1024], line[512], xdisplay[512];
309 char line[512]; 309 char xauthfile[PATH_MAX], xauthdir[PATH_MAX];
310 char xdisplay[512];
311 static char proto[512], data[512]; 310 static char proto[512], data[512];
312 FILE *f; 311 FILE *f;
313 int got_data = 0, generated = 0, do_unlink = 0, i; 312 int got_data = 0, generated = 0, do_unlink = 0, i, r;
314 char *xauthdir, *xauthfile;
315 struct stat st; 313 struct stat st;
316 u_int now, x11_timeout_real; 314 u_int now, x11_timeout_real;
317 315
318 xauthdir = xauthfile = NULL;
319 *_proto = proto; 316 *_proto = proto;
320 *_data = data; 317 *_data = data;
321 proto[0] = data[0] = '\0'; 318 proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0';
322 319
323 if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) { 320 if (!client_x11_display_valid(display)) {
321 if (display != NULL)
322 logit("DISPLAY \"%s\" invalid; disabling X11 forwarding",
323 display);
324 return -1;
325 }
326 if (xauth_path != NULL && stat(xauth_path, &st) == -1) {
324 debug("No xauth program."); 327 debug("No xauth program.");
325 } else if (!client_x11_display_valid(display)) { 328 xauth_path = NULL;
326 logit("DISPLAY '%s' invalid, falling back to fake xauth data", 329 }
327 display); 330
328 } else { 331 if (xauth_path != NULL) {
329 if (display == NULL) {
330 debug("x11_get_proto: DISPLAY not set");
331 return;
332 }
333 /* 332 /*
334 * Handle FamilyLocal case where $DISPLAY does 333 * Handle FamilyLocal case where $DISPLAY does
335 * not match an authorization entry. For this we 334 * not match an authorization entry. For this we
@@ -338,45 +337,60 @@ client_x11_get_proto(const char *display, const char *xauth_path,
338 * is not perfect. 337 * is not perfect.
339 */ 338 */
340 if (strncmp(display, "localhost:", 10) == 0) { 339 if (strncmp(display, "localhost:", 10) == 0) {
341 snprintf(xdisplay, sizeof(xdisplay), "unix:%s", 340 if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
342 display + 10); 341 display + 10)) < 0 ||
342 (size_t)r >= sizeof(xdisplay)) {
343 error("%s: display name too long", __func__);
344 return -1;
345 }
343 display = xdisplay; 346 display = xdisplay;
344 } 347 }
345 if (trusted == 0) { 348 if (trusted == 0) {
346 xauthdir = xmalloc(PATH_MAX);
347 xauthfile = xmalloc(PATH_MAX);
348 mktemp_proto(xauthdir, PATH_MAX);
349 /* 349 /*
350 * Generate an untrusted X11 auth cookie.
351 *
350 * The authentication cookie should briefly outlive 352 * The authentication cookie should briefly outlive
351 * ssh's willingness to forward X11 connections to 353 * ssh's willingness to forward X11 connections to
352 * avoid nasty fail-open behaviour in the X server. 354 * avoid nasty fail-open behaviour in the X server.
353 */ 355 */
356 mktemp_proto(xauthdir, sizeof(xauthdir));
357 if (mkdtemp(xauthdir) == NULL) {
358 error("%s: mkdtemp: %s",
359 __func__, strerror(errno));
360 return -1;
361 }
362 do_unlink = 1;
363 if ((r = snprintf(xauthfile, sizeof(xauthfile),
364 "%s/xauthfile", xauthdir)) < 0 ||
365 (size_t)r >= sizeof(xauthfile)) {
366 error("%s: xauthfile path too long", __func__);
367 unlink(xauthfile);
368 rmdir(xauthdir);
369 return -1;
370 }
371
354 if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK) 372 if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK)
355 x11_timeout_real = UINT_MAX; 373 x11_timeout_real = UINT_MAX;
356 else 374 else
357 x11_timeout_real = timeout + X11_TIMEOUT_SLACK; 375 x11_timeout_real = timeout + X11_TIMEOUT_SLACK;
358 if (mkdtemp(xauthdir) != NULL) { 376 if ((r = snprintf(cmd, sizeof(cmd),
359 do_unlink = 1; 377 "%s -f %s generate %s " SSH_X11_PROTO
360 snprintf(xauthfile, PATH_MAX, "%s/xauthfile", 378 " untrusted timeout %u 2>" _PATH_DEVNULL,
361 xauthdir); 379 xauth_path, xauthfile, display,
362 snprintf(cmd, sizeof(cmd), 380 x11_timeout_real)) < 0 ||
363 "%s -f %s generate %s " SSH_X11_PROTO 381 (size_t)r >= sizeof(cmd))
364 " untrusted timeout %u 2>" _PATH_DEVNULL, 382 fatal("%s: cmd too long", __func__);
365 xauth_path, xauthfile, display, 383 debug2("%s: %s", __func__, cmd);
366 x11_timeout_real); 384 if (x11_refuse_time == 0) {
367 debug2("x11_get_proto: %s", cmd); 385 now = monotime() + 1;
368 if (x11_refuse_time == 0) { 386 if (UINT_MAX - timeout < now)
369 now = monotime() + 1; 387 x11_refuse_time = UINT_MAX;
370 if (UINT_MAX - timeout < now) 388 else
371 x11_refuse_time = UINT_MAX; 389 x11_refuse_time = now + timeout;
372 else 390 channel_set_x11_refuse_time(x11_refuse_time);
373 x11_refuse_time = now + timeout;
374 channel_set_x11_refuse_time(
375 x11_refuse_time);
376 }
377 if (system(cmd) == 0)
378 generated = 1;
379 } 391 }
392 if (system(cmd) == 0)
393 generated = 1;
380 } 394 }
381 395
382 /* 396 /*
@@ -398,17 +412,20 @@ client_x11_get_proto(const char *display, const char *xauth_path,
398 got_data = 1; 412 got_data = 1;
399 if (f) 413 if (f)
400 pclose(f); 414 pclose(f);
401 } else 415 }
402 error("Warning: untrusted X11 forwarding setup failed: "
403 "xauth key data not generated");
404 } 416 }
405 417
406 if (do_unlink) { 418 if (do_unlink) {
407 unlink(xauthfile); 419 unlink(xauthfile);
408 rmdir(xauthdir); 420 rmdir(xauthdir);
409 } 421 }
410 free(xauthdir); 422
411 free(xauthfile); 423 /* Don't fall back to fake X11 data for untrusted forwarding */
424 if (!trusted && !got_data) {
425 error("Warning: untrusted X11 forwarding setup failed: "
426 "xauth key data not generated");
427 return -1;
428 }
412 429
413 /* 430 /*
414 * If we didn't get authentication data, just make up some 431 * If we didn't get authentication data, just make up some
@@ -432,6 +449,8 @@ client_x11_get_proto(const char *display, const char *xauth_path,
432 rnd >>= 8; 449 rnd >>= 8;
433 } 450 }
434 } 451 }
452
453 return 0;
435} 454}
436 455
437/* 456/*
@@ -735,7 +754,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
735static void 754static void
736client_process_net_input(fd_set *readset) 755client_process_net_input(fd_set *readset)
737{ 756{
738 int len, cont = 0; 757 int len;
739 char buf[SSH_IOBUFSZ]; 758 char buf[SSH_IOBUFSZ];
740 759
741 /* 760 /*
@@ -744,8 +763,8 @@ client_process_net_input(fd_set *readset)
744 */ 763 */
745 if (FD_ISSET(connection_in, readset)) { 764 if (FD_ISSET(connection_in, readset)) {
746 /* Read as much as possible. */ 765 /* Read as much as possible. */
747 len = roaming_read(connection_in, buf, sizeof(buf), &cont); 766 len = read(connection_in, buf, sizeof(buf));
748 if (len == 0 && cont == 0) { 767 if (len == 0) {
749 /* 768 /*
750 * Received EOF. The remote host has closed the 769 * Received EOF. The remote host has closed the
751 * connection. 770 * connection.
@@ -1483,13 +1502,43 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1483{ 1502{
1484 fd_set *readset = NULL, *writeset = NULL; 1503 fd_set *readset = NULL, *writeset = NULL;
1485 double start_time, total_time; 1504 double start_time, total_time;
1486 int r, max_fd = 0, max_fd2 = 0, len, rekeying = 0; 1505 int r, max_fd = 0, max_fd2 = 0, len;
1487 u_int64_t ibytes, obytes; 1506 u_int64_t ibytes, obytes;
1488 u_int nalloc = 0; 1507 u_int nalloc = 0;
1489 char buf[100]; 1508 char buf[100];
1490 1509
1491 debug("Entering interactive session."); 1510 debug("Entering interactive session.");
1492 1511
1512 if (options.control_master &&
1513 ! option_clear_or_none(options.control_path)) {
1514 debug("pledge: id");
1515 if (pledge("stdio rpath wpath cpath unix inet dns proc exec id tty",
1516 NULL) == -1)
1517 fatal("%s pledge(): %s", __func__, strerror(errno));
1518
1519 } else if (options.forward_x11 || options.permit_local_command) {
1520 debug("pledge: exec");
1521 if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
1522 NULL) == -1)
1523 fatal("%s pledge(): %s", __func__, strerror(errno));
1524
1525 } else if (options.update_hostkeys) {
1526 debug("pledge: filesystem full");
1527 if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
1528 NULL) == -1)
1529 fatal("%s pledge(): %s", __func__, strerror(errno));
1530
1531 } else if (! option_clear_or_none(options.proxy_command)) {
1532 debug("pledge: proc");
1533 if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1)
1534 fatal("%s pledge(): %s", __func__, strerror(errno));
1535
1536 } else {
1537 debug("pledge: network");
1538 if (pledge("stdio unix inet dns tty", NULL) == -1)
1539 fatal("%s pledge(): %s", __func__, strerror(errno));
1540 }
1541
1493 start_time = get_current_time(); 1542 start_time = get_current_time();
1494 1543
1495 /* Initialize variables. */ 1544 /* Initialize variables. */
@@ -1568,10 +1617,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1568 if (compat20 && session_closed && !channel_still_open()) 1617 if (compat20 && session_closed && !channel_still_open())
1569 break; 1618 break;
1570 1619
1571 rekeying = (active_state->kex != NULL && !active_state->kex->done); 1620 if (ssh_packet_is_rekeying(active_state)) {
1572
1573 if (rekeying) {
1574 debug("rekeying in progress"); 1621 debug("rekeying in progress");
1622 } else if (need_rekeying) {
1623 /* manual rekey request */
1624 debug("need rekeying");
1625 if ((r = kex_start_rekex(active_state)) != 0)
1626 fatal("%s: kex_start_rekex: %s", __func__,
1627 ssh_err(r));
1628 need_rekeying = 0;
1575 } else { 1629 } else {
1576 /* 1630 /*
1577 * Make packets of buffered stdin data, and buffer 1631 * Make packets of buffered stdin data, and buffer
@@ -1602,23 +1656,14 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1602 */ 1656 */
1603 max_fd2 = max_fd; 1657 max_fd2 = max_fd;
1604 client_wait_until_can_do_something(&readset, &writeset, 1658 client_wait_until_can_do_something(&readset, &writeset,
1605 &max_fd2, &nalloc, rekeying); 1659 &max_fd2, &nalloc, ssh_packet_is_rekeying(active_state));
1606 1660
1607 if (quit_pending) 1661 if (quit_pending)
1608 break; 1662 break;
1609 1663
1610 /* Do channel operations unless rekeying in progress. */ 1664 /* Do channel operations unless rekeying in progress. */
1611 if (!rekeying) { 1665 if (!ssh_packet_is_rekeying(active_state))
1612 channel_after_select(readset, writeset); 1666 channel_after_select(readset, writeset);
1613 if (need_rekeying || packet_need_rekeying()) {
1614 debug("need rekeying");
1615 active_state->kex->done = 0;
1616 if ((r = kex_send_kexinit(active_state)) != 0)
1617 fatal("%s: kex_send_kexinit: %s",
1618 __func__, ssh_err(r));
1619 need_rekeying = 0;
1620 }
1621 }
1622 1667
1623 /* Buffer input from the connection. */ 1668 /* Buffer input from the connection. */
1624 client_process_net_input(readset); 1669 client_process_net_input(readset);
@@ -1636,14 +1681,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1636 client_process_output(writeset); 1681 client_process_output(writeset);
1637 } 1682 }
1638 1683
1639 if (session_resumed) {
1640 connection_in = packet_get_connection_in();
1641 connection_out = packet_get_connection_out();
1642 max_fd = MAX(max_fd, connection_out);
1643 max_fd = MAX(max_fd, connection_in);
1644 session_resumed = 0;
1645 }
1646
1647 /* 1684 /*
1648 * Send as much buffered packet data as possible to the 1685 * Send as much buffered packet data as possible to the
1649 * sender. 1686 * sender.
@@ -1737,7 +1774,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1737 } 1774 }
1738 1775
1739 /* Clear and free any buffers. */ 1776 /* Clear and free any buffers. */
1740 memset(buf, 0, sizeof(buf)); 1777 explicit_bzero(buf, sizeof(buf));
1741 buffer_free(&stdin_buffer); 1778 buffer_free(&stdin_buffer);
1742 buffer_free(&stdout_buffer); 1779 buffer_free(&stdout_buffer);
1743 buffer_free(&stderr_buffer); 1780 buffer_free(&stderr_buffer);