DISPLAY=localhost

Kevin Steves
Wed, 05 Dec 2001 21:16:25 -0000

hi,

this can be applied to the latest portable CVS.  by default bind sshd fake
display to localhost.

[stevesk at jenny stevesk]$ uname -sr
HP-UX B.11.11
[stevesk at jenny stevesk]$ echo $DISPLAY
localhost:14.0
[stevesk at jenny stevesk]$ netstat -an|grep 6014
tcp        0      0  127.0.0.1.6014         *.*                     LISTEN

this is currently controlled with sshd_config gatewayports;
gatewayports=yes will revert to old behavior (hostname or IP address
depending on platform).  on hp-ux 11.11 this works with X11 clients using
the R6 libs.  i'd be interested in hearing about results of trying this.
much of it is already commited to the openbsd CVS tree.

Index: includes.h
==================================================================RCS file:
/var/cvs/openssh/includes.h,v
retrieving revision 1.51
diff -u -r1.51 includes.h
--- includes.h	2001/09/20 02:07:51	1.51
+++ includes.h	2001/12/05 20:52:02
@@ -28,6 +28,7 @@
 #include <sys/ioctl.h>
 #include <sys/wait.h>
 #include <sys/resource.h>
+#include <sys/utsname.h>

 #include <netinet/tcp.h>
 #include <arpa/inet.h>
Index: channels.h
==================================================================RCS file:
/var/cvs/openssh/channels.h,v
retrieving revision 1.43
diff -u -r1.43 channels.h
--- channels.h	2001/11/12 00:04:55	1.43
+++ channels.h	2001/12/05 20:52:05
@@ -197,8 +197,7 @@
 /* x11 forwarding */

 int	 x11_connect_display(void);
-char	*x11_create_display(int);
-char	*x11_create_display_inet(int, int);
+int	 x11_create_display_inet(int, int);
 void     x11_input_open(int, int, void *);
 void     x11_request_forwarding(void);
 void	 x11_request_forwarding_with_spoofing(int, const char *, const char *);
Index: channels.c
==================================================================RCS file:
/var/cvs/openssh/channels.c,v
retrieving revision 1.111
diff -u -r1.111 channels.c
--- channels.c	2001/10/12 01:35:05	1.111
+++ channels.c	2001/12/05 20:52:24
@@ -2396,19 +2396,17 @@

 /*
  * Creates an internet domain socket for listening for X11 connections.
- * Returns a suitable value for the DISPLAY variable, or NULL if an error
- * occurs.
+ * Returns a suitable display number for the DISPLAY variable, or -1 if
+ * an error occurs.
  */
-char *
-x11_create_display_inet(int screen_number, int x11_display_offset)
+int
+x11_create_display_inet(int x11_display_offset, int gateway_ports)
 {
 	int display_number, sock;
 	u_short port;
 	struct addrinfo hints, *ai, *aitop;
 	char strport[NI_MAXSERV];
 	int gaierr, n, num_socks = 0, socks[NUM_SOCKS];
-	char display[512];
-	char hostname[MAXHOSTNAMELEN];

 	for (display_number = x11_display_offset;
 	     display_number < MAX_DISPLAYS;
@@ -2416,12 +2414,12 @@
 		port = 6000 + display_number;
 		memset(&hints, 0, sizeof(hints));
 		hints.ai_family = IPv4or6;
-		hints.ai_flags = AI_PASSIVE;		/* XXX loopback only ? */
+		hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
 		hints.ai_socktype = SOCK_STREAM;
 		snprintf(strport, sizeof strport, "%d", port);
 		if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
 			error("getaddrinfo: %.100s", gai_strerror(gaierr));
-			return NULL;
+			return -1;
 		}
 		for (ai = aitop; ai; ai = ai->ai_next) {
 			if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
@@ -2430,7 +2428,7 @@
 			if (sock < 0) {
 				if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) {
 					error("socket: %.100s", strerror(errno));
-					return NULL;
+					return -1;
 				} else {
 					debug("x11_create_display_inet: Socket family %d not supported",
 						 ai->ai_family);
@@ -2466,7 +2464,7 @@
 	}
 	if (display_number >= MAX_DISPLAYS) {
 		error("Failed to allocate internet-domain X11 display socket.");
-		return NULL;
+		return -1;
 	}
 	/* Start listening for connections on the socket. */
 	for (n = 0; n < num_socks; n++) {
@@ -2475,53 +2473,10 @@
 			error("listen: %.100s", strerror(errno));
 			shutdown(sock, SHUT_RDWR);
 			close(sock);
-			return NULL;
+			return -1;
 		}
 	}

-	/* Set up a suitable value for the DISPLAY variable. */
-	if (gethostname(hostname, sizeof(hostname)) < 0)
-		fatal("gethostname: %.100s", strerror(errno));
-
-#ifdef IPADDR_IN_DISPLAY
-	/*
-	 * HPUX detects the local hostname in the DISPLAY variable and tries
-	 * to set up a shared memory connection to the server, which it
-	 * incorrectly supposes to be local.
-	 *
-	 * The workaround - as used in later $$H and other programs - is
-	 * is to set display to the host's IP address.
-	 */
-	{
-		struct hostent *he;
-		struct in_addr my_addr;
-
-		he = gethostbyname(hostname);
-		if (he == NULL) {
-			error("[X11-broken-fwd-hostname-workaround] Could not get "
-				"IP address for hostname %s.", hostname);
-
-			packet_send_debug("[X11-broken-fwd-hostname-workaround]"
-				"Could not get IP address for hostname %s.", hostname);
-
-			shutdown(sock, SHUT_RDWR);
-			close(sock);
-
-			return NULL;
-		}
-
-		memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
-
-		/* Set DISPLAY to <ip address>:screen.display */
-		snprintf(display, sizeof(display), "%.50s:%d.%d",
inet_ntoa(my_addr),
-			 display_number, screen_number);
-	}
-#else /* IPADDR_IN_DISPLAY */
-	/* Just set DISPLAY to hostname:screen.display */
-	snprintf(display, sizeof display, "%.400s:%d.%d", hostname,
-		 display_number, screen_number);
-#endif /* IPADDR_IN_DISPLAY */
-
 	/* Allocate a channel for each socket. */
 	for (n = 0; n < num_socks; n++) {
 		sock = socks[n];
@@ -2531,8 +2486,8 @@
 		    0, xstrdup("X11 inet listener"), 1);
 	}

-	/* Return a suitable value for the DISPLAY environment variable. */
-	return xstrdup(display);
+	/* Return the display number for the DISPLAY environment variable. */
+	return display_number;
 }

 #ifndef X_UNIX_PATH
Index: session.c
==================================================================RCS file:
/var/cvs/openssh/session.c,v
retrieving revision 1.156
diff -u -r1.156 session.c
--- session.c	2001/11/13 12:46:19	1.156
+++ session.c	2001/12/05 20:52:38
@@ -108,8 +108,10 @@
 	int	row, col, xpixel, ypixel;
 	char	tty[TTYSZ];
 	/* X11 */
+	int	display_number;
 	char	*display;
 	int	screen;
+	char	*auth_display[2];
 	char	*auth_proto;
 	char	*auth_data;
 	int	single_connection;
@@ -1415,32 +1417,28 @@
 				    _PATH_SSH_SYSTEM_RC);
 		} else if (do_xauth && options.xauth_location != NULL) {
 			/* Add authority data to .Xauthority if appropriate. */
-			char *screen = strchr(s->display, ':');
-
 			if (debug_flag) {
 				fprintf(stderr,
 				    "Running %.100s add "
 				    "%.100s %.100s %.100s\n",
-				    options.xauth_location, s->display,
+				    options.xauth_location, s->auth_display[0],
 				    s->auth_proto, s->auth_data);
-				if (screen != NULL)
+				if (s->auth_display[1])
 					fprintf(stderr,
-					    "Adding %.*s/unix%s %s %s\n",
-					    (int)(screen - s->display),
-					    s->display, screen,
+					    "add %.100s %.100s %.100s\n",
+					    s->auth_display[1],
 					    s->auth_proto, s->auth_data);
 			}
 			snprintf(cmd, sizeof cmd, "%s -q -",
 			    options.xauth_location);
 			f = popen(cmd, "w");
 			if (f) {
-				fprintf(f, "add %s %s %s\n", s->display,
-				    s->auth_proto, s->auth_data);
-				if (screen != NULL)
-					fprintf(f, "add %.*s/unix%s %s %s\n",
-					    (int)(screen - s->display),
-					    s->display, screen,
-					    s->auth_proto,
+				fprintf(f, "add %s %s %s\n",
+				    s->auth_display[0], s->auth_proto,
+				    s->auth_data);
+				if (s->auth_display[1])
+					fprintf(f, "add %s %s %s\n",
+					    s->auth_display[1], s->auth_proto,
 					    s->auth_data);
 				pclose(f);
 			} else {
@@ -1941,6 +1939,10 @@
 		xfree(s->term);
 	if (s->display)
 		xfree(s->display);
+	if (s->auth_display[0])
+		xfree(s->auth_display[0]);
+	if (s->auth_display[1])
+		xfree(s->auth_display[1]);
 	if (s->auth_data)
 		xfree(s->auth_data);
 	if (s->auth_proto)
@@ -2036,6 +2038,8 @@
 session_setup_x11fwd(Session *s)
 {
 	struct stat st;
+	char display[512], auth_display[512];
+	char hostname[MAXHOSTNAMELEN];

 	if (no_x11_forwarding_flag) {
 		packet_send_debug("X11 forwarding disabled in user configuration
file.");
@@ -2059,11 +2063,68 @@
 		debug("X11 display already set.");
 		return 0;
 	}
-	s->display = x11_create_display_inet(s->screen,
options.x11_display_offset);
-	if (s->display == NULL) {
+	s->display_number = x11_create_display_inet(options.x11_display_offset,
+	    options.gateway_ports);
+	if (s->display_number == -1) {
 		debug("x11_create_display_inet failed.");
 		return 0;
 	}
+
+	/* Set up a suitable value for the DISPLAY variable. */
+	if (gethostname(hostname, sizeof(hostname)) < 0)
+		fatal("gethostname: %.100s", strerror(errno));
+	/*
+	 * auth_display must be used as the displayname when the
+	 * authorization entry is added with xauth(1).  This will be
+	 * different than the DISPLAY string for localhost displays.
+	 */
+	s->auth_display[1] = NULL;
+	if (!options.gateway_ports) {
+		struct utsname uts;
+
+		snprintf(display, sizeof display, "localhost:%d.%d",
+		    s->display_number, s->screen);
+		snprintf(auth_display, sizeof auth_display, "%.400s/unix:%d.%d",
+		    hostname, s->display_number, s->screen);
+		s->display = xstrdup(display);
+		s->auth_display[0] = xstrdup(auth_display);
+		/*
+		 * Xlib may use gethostbyname() or uname() hostname to
+		 * look up authorization data for FamilyLocal; see:
+		 * xc/lib/xtrans/Xtrans.c:TRANS(GetHostname)
+		 * We just add authorization entries with both
+		 * hostname and nodename if they are different.
+		 */
+		if (uname(&uts) == -1)
+			fatal("uname: %.100s", strerror(errno));
+		if (strcmp(hostname, uts.nodename) != 0) {
+			snprintf(auth_display, sizeof auth_display,
+			    "%.400s/unix:%d.%d", uts.nodename,
+			    s->display_number, s->screen);
+			s->auth_display[1] = xstrdup(auth_display);
+		}
+	} else {
+#ifdef IPADDR_IN_DISPLAY
+		struct hostent *he;
+		struct in_addr my_addr;
+
+		he = gethostbyname(hostname);
+		if (he == NULL) {
+			error("Can't get IP address for X11 DISPLAY.");
+			packet_send_debug("Can't get IP address for X11 DISPLAY.");
+			return 0;
+		}
+		memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
+		snprintf(display, sizeof display, "%.50s:%d.%d",
inet_ntoa(my_addr),
+		    s->display_number, s->screen);
+#else
+		snprintf(display, sizeof display, "%.400s:%d.%d", hostname,
+		    s->display_number, s->screen);
+#endif
+		s->display = xstrdup(display);
+		s->auth_display[0] = xstrdup(display);
+	}
+
 	return 1;
 }