summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/clientloop.c')
-rw-r--r--crypto/openssh/clientloop.c195
1 files changed, 116 insertions, 79 deletions
diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c
index 87ceb3d..9820455 100644
--- a/crypto/openssh/clientloop.c
+++ b/crypto/openssh/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.275 2015/07/10 06:21:53 markus Exp $ */
+/* $OpenBSD: clientloop.c,v 1.284 2016/02/08 10:57:07 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -111,7 +111,6 @@
#include "sshpty.h"
#include "match.h"
#include "msg.h"
-#include "roaming.h"
#include "ssherr.h"
#include "hostfile.h"
@@ -169,8 +168,6 @@ static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
static void client_init_dispatch(void);
int session_ident = -1;
-int session_resumed = 0;
-
/* Track escape per proto2 channel */
struct escape_filter_ctx {
int escape_pending;
@@ -288,6 +285,9 @@ client_x11_display_valid(const char *display)
{
size_t i, dlen;
+ if (display == NULL)
+ return 0;
+
dlen = strlen(display);
for (i = 0; i < dlen; i++) {
if (!isalnum((u_char)display[i]) &&
@@ -301,35 +301,34 @@ client_x11_display_valid(const char *display)
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
#define X11_TIMEOUT_SLACK 60
-void
+int
client_x11_get_proto(const char *display, const char *xauth_path,
u_int trusted, u_int timeout, char **_proto, char **_data)
{
- char cmd[1024];
- char line[512];
- char xdisplay[512];
+ char cmd[1024], line[512], xdisplay[512];
+ char xauthfile[PATH_MAX], xauthdir[PATH_MAX];
static char proto[512], data[512];
FILE *f;
- int got_data = 0, generated = 0, do_unlink = 0, i;
- char *xauthdir, *xauthfile;
+ int got_data = 0, generated = 0, do_unlink = 0, i, r;
struct stat st;
u_int now, x11_timeout_real;
- xauthdir = xauthfile = NULL;
*_proto = proto;
*_data = data;
- proto[0] = data[0] = '\0';
+ proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0';
- if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
+ if (!client_x11_display_valid(display)) {
+ if (display != NULL)
+ logit("DISPLAY \"%s\" invalid; disabling X11 forwarding",
+ display);
+ return -1;
+ }
+ if (xauth_path != NULL && stat(xauth_path, &st) == -1) {
debug("No xauth program.");
- } else if (!client_x11_display_valid(display)) {
- logit("DISPLAY '%s' invalid, falling back to fake xauth data",
- display);
- } else {
- if (display == NULL) {
- debug("x11_get_proto: DISPLAY not set");
- return;
- }
+ xauth_path = NULL;
+ }
+
+ if (xauth_path != NULL) {
/*
* Handle FamilyLocal case where $DISPLAY does
* not match an authorization entry. For this we
@@ -338,45 +337,60 @@ client_x11_get_proto(const char *display, const char *xauth_path,
* is not perfect.
*/
if (strncmp(display, "localhost:", 10) == 0) {
- snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
- display + 10);
+ if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
+ display + 10)) < 0 ||
+ (size_t)r >= sizeof(xdisplay)) {
+ error("%s: display name too long", __func__);
+ return -1;
+ }
display = xdisplay;
}
if (trusted == 0) {
- xauthdir = xmalloc(PATH_MAX);
- xauthfile = xmalloc(PATH_MAX);
- mktemp_proto(xauthdir, PATH_MAX);
/*
+ * Generate an untrusted X11 auth cookie.
+ *
* The authentication cookie should briefly outlive
* ssh's willingness to forward X11 connections to
* avoid nasty fail-open behaviour in the X server.
*/
+ mktemp_proto(xauthdir, sizeof(xauthdir));
+ if (mkdtemp(xauthdir) == NULL) {
+ error("%s: mkdtemp: %s",
+ __func__, strerror(errno));
+ return -1;
+ }
+ do_unlink = 1;
+ if ((r = snprintf(xauthfile, sizeof(xauthfile),
+ "%s/xauthfile", xauthdir)) < 0 ||
+ (size_t)r >= sizeof(xauthfile)) {
+ error("%s: xauthfile path too long", __func__);
+ unlink(xauthfile);
+ rmdir(xauthdir);
+ return -1;
+ }
+
if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK)
x11_timeout_real = UINT_MAX;
else
x11_timeout_real = timeout + X11_TIMEOUT_SLACK;
- if (mkdtemp(xauthdir) != NULL) {
- do_unlink = 1;
- snprintf(xauthfile, PATH_MAX, "%s/xauthfile",
- xauthdir);
- snprintf(cmd, sizeof(cmd),
- "%s -f %s generate %s " SSH_X11_PROTO
- " untrusted timeout %u 2>" _PATH_DEVNULL,
- xauth_path, xauthfile, display,
- x11_timeout_real);
- debug2("x11_get_proto: %s", cmd);
- if (x11_refuse_time == 0) {
- now = monotime() + 1;
- if (UINT_MAX - timeout < now)
- x11_refuse_time = UINT_MAX;
- else
- x11_refuse_time = now + timeout;
- channel_set_x11_refuse_time(
- x11_refuse_time);
- }
- if (system(cmd) == 0)
- generated = 1;
+ if ((r = snprintf(cmd, sizeof(cmd),
+ "%s -f %s generate %s " SSH_X11_PROTO
+ " untrusted timeout %u 2>" _PATH_DEVNULL,
+ xauth_path, xauthfile, display,
+ x11_timeout_real)) < 0 ||
+ (size_t)r >= sizeof(cmd))
+ fatal("%s: cmd too long", __func__);
+ debug2("%s: %s", __func__, cmd);
+ if (x11_refuse_time == 0) {
+ now = monotime() + 1;
+ if (UINT_MAX - timeout < now)
+ x11_refuse_time = UINT_MAX;
+ else
+ x11_refuse_time = now + timeout;
+ channel_set_x11_refuse_time(x11_refuse_time);
}
+ if (system(cmd) == 0)
+ generated = 1;
}
/*
@@ -398,17 +412,20 @@ client_x11_get_proto(const char *display, const char *xauth_path,
got_data = 1;
if (f)
pclose(f);
- } else
- error("Warning: untrusted X11 forwarding setup failed: "
- "xauth key data not generated");
+ }
}
if (do_unlink) {
unlink(xauthfile);
rmdir(xauthdir);
}
- free(xauthdir);
- free(xauthfile);
+
+ /* Don't fall back to fake X11 data for untrusted forwarding */
+ if (!trusted && !got_data) {
+ error("Warning: untrusted X11 forwarding setup failed: "
+ "xauth key data not generated");
+ return -1;
+ }
/*
* 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,
rnd >>= 8;
}
}
+
+ return 0;
}
/*
@@ -735,7 +754,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
static void
client_process_net_input(fd_set *readset)
{
- int len, cont = 0;
+ int len;
char buf[SSH_IOBUFSZ];
/*
@@ -744,8 +763,8 @@ client_process_net_input(fd_set *readset)
*/
if (FD_ISSET(connection_in, readset)) {
/* Read as much as possible. */
- len = roaming_read(connection_in, buf, sizeof(buf), &cont);
- if (len == 0 && cont == 0) {
+ len = read(connection_in, buf, sizeof(buf));
+ if (len == 0) {
/*
* Received EOF. The remote host has closed the
* connection.
@@ -1483,13 +1502,43 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
{
fd_set *readset = NULL, *writeset = NULL;
double start_time, total_time;
- int r, max_fd = 0, max_fd2 = 0, len, rekeying = 0;
+ int r, max_fd = 0, max_fd2 = 0, len;
u_int64_t ibytes, obytes;
u_int nalloc = 0;
char buf[100];
debug("Entering interactive session.");
+ if (options.control_master &&
+ ! option_clear_or_none(options.control_path)) {
+ debug("pledge: id");
+ if (pledge("stdio rpath wpath cpath unix inet dns proc exec id tty",
+ NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+
+ } else if (options.forward_x11 || options.permit_local_command) {
+ debug("pledge: exec");
+ if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
+ NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+
+ } else if (options.update_hostkeys) {
+ debug("pledge: filesystem full");
+ if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
+ NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+
+ } else if (! option_clear_or_none(options.proxy_command)) {
+ debug("pledge: proc");
+ if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+
+ } else {
+ debug("pledge: network");
+ if (pledge("stdio unix inet dns tty", NULL) == -1)
+ fatal("%s pledge(): %s", __func__, strerror(errno));
+ }
+
start_time = get_current_time();
/* Initialize variables. */
@@ -1568,10 +1617,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
if (compat20 && session_closed && !channel_still_open())
break;
- rekeying = (active_state->kex != NULL && !active_state->kex->done);
-
- if (rekeying) {
+ if (ssh_packet_is_rekeying(active_state)) {
debug("rekeying in progress");
+ } else if (need_rekeying) {
+ /* manual rekey request */
+ debug("need rekeying");
+ if ((r = kex_start_rekex(active_state)) != 0)
+ fatal("%s: kex_start_rekex: %s", __func__,
+ ssh_err(r));
+ need_rekeying = 0;
} else {
/*
* 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)
*/
max_fd2 = max_fd;
client_wait_until_can_do_something(&readset, &writeset,
- &max_fd2, &nalloc, rekeying);
+ &max_fd2, &nalloc, ssh_packet_is_rekeying(active_state));
if (quit_pending)
break;
/* Do channel operations unless rekeying in progress. */
- if (!rekeying) {
+ if (!ssh_packet_is_rekeying(active_state))
channel_after_select(readset, writeset);
- if (need_rekeying || packet_need_rekeying()) {
- debug("need rekeying");
- active_state->kex->done = 0;
- if ((r = kex_send_kexinit(active_state)) != 0)
- fatal("%s: kex_send_kexinit: %s",
- __func__, ssh_err(r));
- need_rekeying = 0;
- }
- }
/* Buffer input from the connection. */
client_process_net_input(readset);
@@ -1636,14 +1681,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
client_process_output(writeset);
}
- if (session_resumed) {
- connection_in = packet_get_connection_in();
- connection_out = packet_get_connection_out();
- max_fd = MAX(max_fd, connection_out);
- max_fd = MAX(max_fd, connection_in);
- session_resumed = 0;
- }
-
/*
* Send as much buffered packet data as possible to the
* sender.
@@ -1737,7 +1774,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
}
/* Clear and free any buffers. */
- memset(buf, 0, sizeof(buf));
+ explicit_bzero(buf, sizeof(buf));
buffer_free(&stdin_buffer);
buffer_free(&stdout_buffer);
buffer_free(&stderr_buffer);
OpenPOWER on IntegriCloud