diff options
Diffstat (limited to 'clientloop.c')
| -rw-r--r-- | clientloop.c | 195 | 
1 files changed, 116 insertions, 79 deletions
diff --git a/clientloop.c b/clientloop.c index 87ceb3dab9e6..9820455c4293 100644 --- a/clientloop.c +++ b/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);  | 
