# HG changeset patch
# Parent  4be82a7dfb4e92ca325bbb58aea3cf95f726d785
Upstream commit 1ab6a51f9b258a6e844f1ee442c15aec7fcb6a72
Author: Damien Miller <djm@mindrot.org>
Date:   Sat Jun 26 10:02:24 2010 +1000

       - djm@cvs.openbsd.org 2010/06/25 23:10:30
         [ssh.c]
         log the hostname and address that we connected to at LogLevel=verbose
         after authentication is successful to mitigate "phishing" attacks by
         servers with trusted keys that accept authentication silently and
         automatically before presenting fake password/passphrase prompts;
         "nice!" markus@

diff --git a/openssh-5.1p1/clientloop.c b/openssh-5.1p1/clientloop.c
--- a/openssh-5.1p1/clientloop.c
+++ b/openssh-5.1p1/clientloop.c
@@ -147,21 +147,22 @@ static volatile sig_atomic_t quit_pendin
 static int escape_char1;	/* Escape character. (proto1 only) */
 static int escape_pending1;	/* Last character was an escape (proto1 only) */
 static int last_was_cr;		/* Last character was a newline. */
 static int exit_status;		/* Used to store the command exit status. */
 static int stdin_eof;		/* EOF has been encountered on stderr. */
 static Buffer stdin_buffer;	/* Buffer for stdin data. */
 static Buffer stdout_buffer;	/* Buffer for stdout data. */
 static Buffer stderr_buffer;	/* Buffer for stderr data. */
-static u_int buffer_high;/* Soft max buffer size. */
+static u_int buffer_high;	/* Soft max buffer size. */
 static int connection_in;	/* Connection to server (input). */
 static int connection_out;	/* Connection to server (output). */
 static int need_rekeying;	/* Set to non-zero if rekeying is requested. */
-static int session_closed = 0;	/* In SSH2: login session closed. */
+static int session_closed;	/* In SSH2: login session closed. */
+static int x11_refuse_time;	/* If >0, refuse x11 opens after this time. */
 
 static void client_init_dispatch(void);
 int	session_ident = -1;
 
 /* Track escape per proto2 channel */
 struct escape_filter_ctx {
 	int escape_pending;
 	int escape_char;
@@ -244,26 +245,27 @@ get_current_time(void)
 	struct timeval tv;
 	gettimeofday(&tv, NULL);
 	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
 }
 
 #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
 void
 client_x11_get_proto(const char *display, const char *xauth_path,
-    u_int trusted, char **_proto, char **_data)
+    u_int trusted, u_int timeout, char **_proto, char **_data)
 {
 	char cmd[1024];
 	char line[512];
 	char xdisplay[512];
 	static char proto[512], data[512];
 	FILE *f;
 	int got_data = 0, generated = 0, do_unlink = 0, i;
 	char *xauthdir, *xauthfile;
 	struct stat st;
+	u_int now;
 
 	xauthdir = xauthfile = NULL;
 	*_proto = proto;
 	*_data = data;
 	proto[0] = data[0] = '\0';
 
 	if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
 		debug("No xauth program.");
@@ -289,21 +291,28 @@ client_x11_get_proto(const char *display
 			xauthfile = xmalloc(MAXPATHLEN);
 			strlcpy(xauthdir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
 			if (mkdtemp(xauthdir) != NULL) {
 				do_unlink = 1;
 				snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
 				    xauthdir);
 				snprintf(cmd, sizeof(cmd),
 				    "%s -f %s generate %s " SSH_X11_PROTO
-				    " untrusted timeout 1200 2>" _PATH_DEVNULL,
-				    xauth_path, xauthfile, display);
+				    " untrusted timeout %u 2>" _PATH_DEVNULL,
+				    xauth_path, xauthfile, display, timeout);
 				debug2("x11_get_proto: %s", cmd);
 				if (system(cmd) == 0)
 					generated = 1;
+				if (x11_refuse_time == 0) {
+					now = time(NULL) + 1;
+					if (UINT_MAX - timeout < now)
+						x11_refuse_time = UINT_MAX;
+					else
+						x11_refuse_time = now + timeout;
+				}
 			}
 		}
 
 		/*
 		 * When in untrusted mode, we read the cookie only if it was
 		 * successfully generated as an untrusted one in the step
 		 * above.
 		 */
@@ -1662,16 +1671,21 @@ client_request_x11(const char *request_t
 	int sock;
 
 	if (!options.forward_x11) {
 		error("Warning: ssh server tried X11 forwarding.");
 		error("Warning: this is probably a break-in attempt by a "
 		    "malicious server.");
 		return NULL;
 	}
+	if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) {
+		verbose("Rejected X11 connection after ForwardX11Timeout "
+		    "expired");
+		return NULL;
+	}
 	originator = packet_get_string(NULL);
 	if (datafellows & SSH_BUG_X11FWD) {
 		debug2("buggy server: x11 request w/o originator_port");
 		originator_port = 0;
 	} else {
 		originator_port = packet_get_int();
 	}
 	packet_check_eom();
diff --git a/openssh-5.1p1/clientloop.h b/openssh-5.1p1/clientloop.h
--- a/openssh-5.1p1/clientloop.h
+++ b/openssh-5.1p1/clientloop.h
@@ -34,17 +34,17 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <termios.h>
 
 /* Client side main loop for the interactive session. */
 int	 client_loop(int, int, int);
-void	 client_x11_get_proto(const char *, const char *, u_int,
+void	 client_x11_get_proto(const char *, const char *, u_int, u_int,
 	    char **, char **);
 void	 client_global_request_reply_fwd(int, u_int32_t, void *);
 void	 client_session2_setup(int, int, int, const char *, struct termios *,
 	    int, Buffer *, char **);
 int	 client_request_tun_fwd(int, int, int);
 
 /* Escape filter for protocol 2 sessions */
 void	*client_new_escape_filter_ctx(int);
diff --git a/openssh-5.1p1/mux.c b/openssh-5.1p1/mux.c
--- a/openssh-5.1p1/mux.c
+++ b/openssh-5.1p1/mux.c
@@ -176,21 +176,24 @@ mux_session_confirm(int id, void *arg)
 	if (cctx == NULL)
 		fatal("%s: cctx == NULL", __func__);
 	if ((c = channel_lookup(id)) == NULL)
 		fatal("%s: no channel for id %d", __func__, id);
 
 	display = getenv("DISPLAY");
 	if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
 		char *proto, *data;
+
 		/* Get reasonable local authentication information. */
 		client_x11_get_proto(display, options.xauth_location,
-		    options.forward_x11_trusted, &proto, &data);
+		    options.forward_x11_trusted, options.forward_x11_timeout,
+		    &proto, &data);
 		/* Request forwarding with authentication spoofing. */
-		debug("Requesting X11 forwarding with authentication spoofing.");
+		debug("Requesting X11 forwarding with authentication "
+		    "spoofing.");
 		x11_request_forwarding_with_spoofing(id, display, proto, data);
 		/* XXX wait for reply */
 	}
 
 	if (cctx->want_agent_fwd && options.forward_agent) {
 		debug("Requesting authentication agent forwarding.");
 		channel_request_start(id, "auth-agent-req@openssh.com", 0);
 		packet_send();
diff --git a/openssh-5.1p1/readconf.c b/openssh-5.1p1/readconf.c
--- a/openssh-5.1p1/readconf.c
+++ b/openssh-5.1p1/readconf.c
@@ -106,18 +106,18 @@
      EscapeChar ~
 
 */
 
 /* Keyword tokens. */
 
 typedef enum {
 	oBadOption,
-	oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
-	oExitOnForwardFailure,
+	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
+	oGatewayPorts, oExitOnForwardFailure,
 	oPasswordAuthentication, oRSAAuthentication,
 	oChallengeResponseAuthentication, oXAuthLocation,
 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
 	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
@@ -140,16 +140,17 @@ typedef enum {
 
 static struct {
 	const char *name;
 	OpCodes opcode;
 } keywords[] = {
 	{ "forwardagent", oForwardAgent },
 	{ "forwardx11", oForwardX11 },
 	{ "forwardx11trusted", oForwardX11Trusted },
+	{ "forwardx11timeout", oForwardX11Timeout },
 	{ "exitonforwardfailure", oExitOnForwardFailure },
 	{ "xauthlocation", oXAuthLocation },
 	{ "gatewayports", oGatewayPorts },
 	{ "useprivilegedport", oUsePrivilegedPort },
 	{ "rhostsauthentication", oDeprecated },
 	{ "passwordauthentication", oPasswordAuthentication },
 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
@@ -398,16 +399,20 @@ parse_flag:
 
 	case oForwardX11:
 		intptr = &options->forward_x11;
 		goto parse_flag;
 
 	case oForwardX11Trusted:
 		intptr = &options->forward_x11_trusted;
 		goto parse_flag;
+	
+	case oForwardX11Timeout:
+		intptr = &options->forward_x11_timeout;
+		goto parse_time;
 
 	case oGatewayPorts:
 		intptr = &options->gateway_ports;
 		goto parse_flag;
 
 	case oExitOnForwardFailure:
 		intptr = &options->exit_on_forward_failure;
 		goto parse_flag;
@@ -1019,16 +1024,17 @@ read_config_file(const char *filename, c
 
 void
 initialize_options(Options * options)
 {
 	memset(options, 'X', sizeof(*options));
 	options->forward_agent = -1;
 	options->forward_x11 = -1;
 	options->forward_x11_trusted = -1;
+	options->forward_x11_timeout = -1;
 	options->exit_on_forward_failure = -1;
 	options->xauth_location = NULL;
 	options->gateway_ports = -1;
 	options->use_privileged_port = -1;
 	options->rsa_authentication = -1;
 	options->pubkey_authentication = -1;
 	options->challenge_response_authentication = -1;
 	options->gss_authentication = -1;
@@ -1103,16 +1109,18 @@ fill_default_options(Options * options)
 	int len;
 
 	if (options->forward_agent == -1)
 		options->forward_agent = 0;
 	if (options->forward_x11 == -1)
 		options->forward_x11 = 0;
 	if (options->forward_x11_trusted == -1)
 		options->forward_x11_trusted = 0;
+	if (options->forward_x11_timeout == -1)
+		options->forward_x11_timeout = 1200;
 	if (options->exit_on_forward_failure == -1)
 		options->exit_on_forward_failure = 0;
 	if (options->xauth_location == NULL)
 		options->xauth_location = _PATH_XAUTH;
 	if (options->gateway_ports == -1)
 		options->gateway_ports = 0;
 	if (options->use_privileged_port == -1)
 		options->use_privileged_port = 0;
diff --git a/openssh-5.1p1/readconf.h b/openssh-5.1p1/readconf.h
--- a/openssh-5.1p1/readconf.h
+++ b/openssh-5.1p1/readconf.h
@@ -26,16 +26,17 @@ typedef struct {
 }       Forward;
 /* Data structure for representing option data. */
 
 #define MAX_SEND_ENV	256
 
 typedef struct {
 	int     forward_agent;	/* Forward authentication agent. */
 	int     forward_x11;	/* Forward X11 display. */
+	int     forward_x11_timeout;	/* Expiration for Cookies */
 	int     forward_x11_trusted;	/* Trust Forward X11 display. */
 	int     exit_on_forward_failure;	/* Exit if bind(2) fails for -L/-R */
 	char   *xauth_location;	/* Location for xauth program */
 	int     gateway_ports;	/* Allow remote connects to forwarded ports. */
 	int     use_privileged_port;	/* Don't use privileged port if false. */
 	int     rhosts_rsa_authentication;	/* Try rhosts with RSA
 						 * authentication. */
 	int     rsa_authentication;	/* Try RSA authentication. */
diff --git a/openssh-5.1p1/ssh.c b/openssh-5.1p1/ssh.c
--- a/openssh-5.1p1/ssh.c
+++ b/openssh-5.1p1/ssh.c
@@ -1046,17 +1046,18 @@ ssh_session(void)
 			    "request response.");
 	}
 	/* Request X11 forwarding if enabled and DISPLAY is set. */
 	display = getenv("DISPLAY");
 	if (options.forward_x11 && display != NULL) {
 		char *proto, *data;
 		/* Get reasonable local authentication information. */
 		client_x11_get_proto(display, options.xauth_location,
-		    options.forward_x11_trusted, &proto, &data);
+		    options.forward_x11_trusted,
+		    options.forward_x11_timeout, &proto, &data);
 		/* Request forwarding with authentication spoofing. */
 		debug("Requesting X11 forwarding with authentication "
 		    "spoofing.");
 		x11_request_forwarding_with_spoofing(0, display, proto, data);
 
 		/* Read response from the server. */
 		type = packet_read();
 		if (type == SSH_SMSG_SUCCESS) {
@@ -1139,17 +1140,19 @@ ssh_session2_setup(int id, void *arg)
 	const char *display;
 	int interactive = tty_flag;
 
 	display = getenv("DISPLAY");
 	if (options.forward_x11 && display != NULL) {
 		char *proto, *data;
 		/* Get reasonable local authentication information. */
 		client_x11_get_proto(display, options.xauth_location,
-		    options.forward_x11_trusted, &proto, &data);
+		    options.forward_x11_trusted, 
+		    options.forward_x11_timeout,
+		    &proto, &data);
 		/* Request forwarding with authentication spoofing. */
 		debug("Requesting X11 forwarding with authentication "
 		    "spoofing.");
 		x11_request_forwarding_with_spoofing(id, display, proto, data);
 		interactive = 1;
 		/* XXX wait for reply */
 	}
 
diff --git a/openssh-5.1p1/ssh_config.5 b/openssh-5.1p1/ssh_config.5
--- a/openssh-5.1p1/ssh_config.5
+++ b/openssh-5.1p1/ssh_config.5
@@ -427,16 +427,26 @@ The default is
 X11 forwarding should be enabled with caution.
 Users with the ability to bypass file permissions on the remote host
 (for the user's X11 authorization database)
 can access the local X11 display through the forwarded connection.
 An attacker may then be able to perform activities such as keystroke monitoring
 if the
 .Cm ForwardX11Trusted
 option is also enabled.
+.It Cm ForwardX11Timeout
+Specify a timeout for untrusted X11 forwarding using the format described in
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+X11 connections received by
+.Xr ssh 1
+after this time will be refused.
+The default is to disable untrusted X11 forwarding after twenty minutes has
+elapsed.
 .It Cm ForwardX11Trusted
 If this option is set to
 .Dq yes ,
 remote X11 clients will have full access to the original X11 display.
 .Pp
 If this option is set to
 .Dq no ,
 remote X11 clients will be considered untrusted and prevented
