ssh -X does not work on Yosemite

Can no longer use X11 with ssh. Have XQuartz2.7.7 installed. Logging in with X11 via ssh gives the warnings

Warning: untrusted X11 forwarding setup failed: xauth key data not generated Warning: No xauth data; using fake authentication data for X11 forwarding.

In my own system, echo $DISPLAY gives

/private/tmp/com.apple.launchd.GuewxwWwKS/org.macosforge.xquartz:0

However, when I try xauth generate $DISPLAY . trusted, I get the error

xauth: (argv):1: bad display name "/private/tmp/com.apple.launchd.GuewxwWwKS/org.macosforge.xquartz:0" in "add" command

Any ideas in how to fix this?


Solution 1:

UPDATE

Developer Jeremy Huddleston Sequoia announced yesterday that this problem is solved in XQuartz 2.7.8_beta2:

XQuartz 2.7.8_beta2 is available for download.

You can see http://xquartz.macosforge.org/trac/wiki/X112.7.8 for a full set of changes, but most noteworth ones are:

1) xauth now correctly parses the Yosemite launchd $DISPLAY socket path
2) libGL has been updated to Mesa 10.4.4
3) Various exploits were fixed in xorg-server, freetype, and libpng
4) A bug preventing automatic updates in some cases has been fixed

The bug report is closed and marked as fixed:

enter image description here

If you can't (or don't want to) install the beta, you can still use the workaround I explain below.


ANSWER

Analysis

(scroll down for the workaround section)

My first thought was "the DISPLAY variable is wrong". But it's not.

As it turns out, on OS X 10.10 Yosemite (and back to 10.8 Mountain Lion) the DISPLAY variable stores a launchd socket path:

/private/tmp/<socket name>

instead of the familiar display name:

hostname:displaynumber.screennumber

(I've added some information about the hostname:displaynumber.screennumber format at the end of this answer.)

This means that xauth has to know how to deal with this special incarnation of the DISPLAY variable, and as of Mavericks, it did, but the socket used in Yosemite has a different path (more precisely: /private/tmp/com.apple.launchd.XXXX instead of /private/tmp/launch-XXXX), and xauth breaks.

This bug was reported to the XQuartz team on Nov 18 2014 (3 months ago) (http://xquartz.macosforge.org/trac/ticket/2068):

The xauth program has code in both gethost.c and parsedpy.c to look for $DISPLAY names that start with "/tmp/launch", and to treat that as a local socket. However, the location seems to have changed, $DISPLAY now starts with "/private/tmp/com.apple.launchd", so the code that is looking for /tmp/launch doesn't catch it. (...)

According to the bug description it is to be solved in XQuartz 2.7.8, which is 4 months late (see the project roadmap page at http://xquartz.macosforge.org/trac/roadmap).

The patch that fixes the problem was committed on Dec 31 2014 to the freedesktop.org project (http://cgit.freedesktop.org/xorg/app/xauth/commit/parsedpy.c?id=f990dd936b5fd1a40290bb88cde517a0ac38f823):

diff --git a/parsedpy.c b/parsedpy.c
index c591b77..7365224 100644
--- a/parsedpy.c
+++ b/parsedpy.c
@@ -42,6 +42,9 @@ in this Software without prior written authorization from The Open Group.
 #include <X11/Xauth.h>         /* for FamilyLocal */
 #include <X11/Xmu/SysUtil.h>

+#include <sys/stat.h>
+#include <sys/syslimits.h>
+
 #if defined(UNIXCONN) || defined(LOCALCONN)
 #define UNIX_CONNECTION "unix"
 #define UNIX_CONNECTION_LENGTH 4
@@ -158,8 +161,32 @@ parse_displayname (const char *displayname,

     if (!host) return False;

-    if(strncmp (host, "/tmp/launch", 11) == 0) {
-        family = FamilyLocal;
+    {
+        /*
+         * If using launchd socket, remove the screen number from the end
+         * of $DISPLAY and check if it is a path to a socket.
+         */
+        char path[PATH_MAX];
+        struct stat sbuf;
(...)

So it's only a question of time until this patch finds its way into the next release of XQuartz.

Workaround

(tested on OS X 10.10.2 Yosemite.)

Add:

alias ssh="ln -fs $(echo $DISPLAY | sed 's:\(/private/tmp/com\.apple\.launchd\.[^/]*\)/.*:\1:') $(echo $DISPLAY | sed 's:/private/tmp/com\.apple\.launchd\.\([^/]*\)/.*:/private/tmp/launch-\1:'); ssh"

to ~/.bashrc and either start a new Terminal window or source it (. ~/.bashrc) in your current Terminal session.

This alias first symlinks the socket path to /private/tmp/launch-XXX (for example ln -fs /private/tmp/com.apple.launchd.GuewxwWwKS /private/tmp/launch-GuewxwWwKS) and then starts ssh:

enter image description here


For the curious, traditionally, the X server's display name has had this form (from man X on Ubuntu): The X server's display name has this form:

hostname:displaynumber.screennumber

where:

   hostname
           The hostname specifies the name of the machine to which the display  is  physically
           connected.   If  the hostname is not given, the most efficient way of communicating
           to a server on the same machine will be used.

   displaynumber
           The phrase "display" is usually used to refer to  a  collection  of  monitors  that
           share a common set of input devices (keyboard, mouse, tablet, etc.).  Most worksta‐
           tions tend to only have one display.  Larger,  multi-user  systems,  however,  fre‐
           quently  have  several  displays so that more than one person can be doing graphics
           work at once.  To avoid confusion, each display on a machine is assigned a  display
           number (beginning at 0) when the X server for that display is started.  The display
           number must always be given in a display name.

   screennumber
           Some displays share their input devices among two or more monitors.  These  may  be
           configured as a single logical screen, which allows windows to move across screens,
           or as individual screens, each with their own set of windows.  If  configured  such
           that each monitor has its own set of windows, each screen is assigned a screen num‐
           ber (beginning at 0) when the X server for that display is started.  If the  screen
           number is not given, screen 0 will be used.