diff options
Diffstat (limited to 'crypto/openssh/clientloop.c')
-rw-r--r-- | crypto/openssh/clientloop.c | 195 |
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); |