19130869 migrate the Xforwarding bug fix (15350344) from SunSSH to OpenSSH
authorHuie-Ying Lee <huieying.lee@oracle.com>
Thu, 06 Aug 2015 13:59:44 -0700
changeset 4744 ed1ff241f25d
parent 4743 a41b0913b4ea
child 4745 2d05f68d43d8
19130869 migrate the Xforwarding bug fix (15350344) from SunSSH to OpenSSH
components/openssh/Makefile
components/openssh/patches/031-per_session_xauthfile.patch
--- a/components/openssh/Makefile	Fri Jun 05 05:22:16 2015 -0700
+++ b/components/openssh/Makefile	Thu Aug 06 13:59:44 2015 -0700
@@ -59,6 +59,7 @@
 CFLAGS += -DPAM_BUGFIX
 CFLAGS += -DOPTION_DEFAULT_VALUE
 CFLAGS += -DWITHOUT_ED25519
+CFLAGS += -DPER_SESSION_XAUTHFILE
 
 CONFIGURE_OPTIONS += CFLAGS="$(CFLAGS)" 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openssh/patches/031-per_session_xauthfile.patch	Thu Aug 06 13:59:44 2015 -0700
@@ -0,0 +1,191 @@
+#
+# This patch is to fix a X11 connection failure when a user's home directory
+# is read-only. 
+#
+# We have contributed back this fix to the OpenSSH upstream community. For
+# more information, see https://bugzilla.mindrot.org/show_bug.cgi?id=2440
+# In the future, if this fix is accepted by the upsteam in a later release, we
+# will remove this patch when we upgrade to that release.
+#
+--- orig/session.c	Thu Jul 30 10:35:15 2015
++++ new/session.c	Tue Aug  4 11:29:22 2015
+@@ -62,6 +62,10 @@
+ #include <unistd.h>
+ #include <limits.h>
+ 
++#ifdef PER_SESSION_XAUTHFILE
++#include <libgen.h>
++#endif
++
+ #include "openbsd-compat/sys-queue.h"
+ #include "xmalloc.h"
+ #include "ssh.h"
+@@ -132,6 +136,11 @@
+ 
+ static int session_pty_req(Session *);
+ 
++#ifdef PER_SESSION_XAUTHFILE
++void   session_xauthfile_cleanup(Session *);
++void   cleanup_all_session_xauthfile();
++#endif
++
+ /* import */
+ extern ServerOptions options;
+ extern char *__progname;
+@@ -1218,6 +1227,11 @@
+ 	if (getenv("TZ"))
+ 		child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+ 
++#ifdef PER_SESSION_XAUTHFILE
++        if (s->auth_file != NULL)
++                child_set_env(&env, &envsize, "XAUTHORITY", s->auth_file);
++#endif
++
+ 	/* Set custom environment options from RSA authentication. */
+ 	if (!options.use_login) {
+ 		while (custom_environment) {
+@@ -2170,6 +2184,11 @@
+ {
+ 	int success;
+ 
++#ifdef PER_SESSION_XAUTHFILE
++	int fd;
++        char xauthdir[] = "/tmp/ssh-xauth-XXXXXX";
++#endif
++
+ 	if (s->auth_proto != NULL || s->auth_data != NULL) {
+ 		error("session_x11_req: session %d: "
+ 		    "x11 forwarding already active", s->self);
+@@ -2188,6 +2207,48 @@
+ 		s->auth_proto = NULL;
+ 		s->auth_data = NULL;
+ 	}
++
++#ifdef PER_SESSION_XAUTHFILE
++	/*
++	 * Create per session X authority file in the /tmp directory.
++	 *
++	 * If mkdtemp() or open() fails then s->auth_file remains NULL which
++	 * means that we won't set XAUTHORITY variable in child's environment
++	 * and xauth(1) will use the default location for the authority file.
++	 */
++	if (mkdtemp(xauthdir) != NULL) {
++		s->auth_file = xmalloc(MAXPATHLEN);
++		snprintf(s->auth_file, MAXPATHLEN, "%s/xauthfile",
++		    xauthdir);
++		/*
++		 * we don't want that "creating new authority file" message to
++                 * be printed by xauth(1) so we must create that file
++		 * beforehand.
++		 */
++		if ((fd = open(s->auth_file, O_CREAT | O_EXCL | O_RDONLY,
++		    S_IRUSR | S_IWUSR)) == -1) {
++			error("failed to create the temporary X authority "
++			    "file %s: %.100s; will use the default one",
++			    s->auth_file, strerror(errno));
++			free(s->auth_file);
++			s->auth_file = NULL;
++			if (rmdir(xauthdir) == -1) {
++				error("cannot remove xauth directory "
++				    "%s: %.100s", xauthdir, strerror(errno));
++			}
++		} else {
++			close(fd);
++			debug("temporary X authority file %s created",
++			    s->auth_file);
++                        debug("session number = %d", s->self);
++		}
++	}
++	else {
++		error("failed to create a directory for the temporary X "
++		    "authority file: %.100s; will use the default xauth file",
++		    strerror(errno));
++	}
++#endif
+ 	return success;
+ }
+ 
+@@ -2378,6 +2439,50 @@
+ 	PRIVSEP(session_pty_cleanup2(s));
+ }
+ 
++#ifdef PER_SESSION_XAUTHFILE
++/*
++ * We use a different temporary X authority file per session so we should
++ * remove those files when cleanup_exit() is called.
++ */
++void
++session_xauthfile_cleanup(Session *s)
++{
++	if (s == NULL || s->auth_file == NULL) {
++		return;
++	}
++
++	debug("session_xauthfile_cleanup: session %d removing %s", s->self,
++	    s->auth_file);
++
++	if (unlink(s->auth_file) == -1) {
++		error("session_xauthfile_cleanup: cannot remove xauth file: "
++		    "%.100s", strerror(errno));
++		return;
++	}
++
++	/* dirname() will modify s->auth_file but that's ok */
++	if (rmdir(dirname(s->auth_file)) == -1) {
++		error("session_xauthfile_cleanup: "
++		    "cannot remove xauth directory: %.100s", strerror(errno));
++		return;
++	}
++	free(s->auth_file);
++	s->auth_file = NULL;
++}
++
++/*
++ * This is called by do_cleanup() when cleanup_exit() is called. 
++ */
++void
++cleanup_all_session_xauthfile()
++{
++	int i;
++	for (i = 0; i < sessions_nalloc; i++) {
++                session_xauthfile_cleanup(&sessions[i]);
++	}
++}
++#endif
++
+ static char *
+ sig2name(int sig)
+ {
+@@ -2512,6 +2617,9 @@
+ 	free(s->auth_display);
+ 	free(s->auth_data);
+ 	free(s->auth_proto);
++#ifdef PER_SESSION_XAUTHFILE
++	session_xauthfile_cleanup(s);
++#endif
+ 	free(s->subsys);
+ 	if (s->env != NULL) {
+ 		for (i = 0; i < s->num_env; i++) {
+@@ -2763,6 +2871,10 @@
+ 	/* remove agent socket */
+ 	auth_sock_cleanup_proc(authctxt->pw);
+ 
++#ifdef PER_SESSION_XAUTHFILE
++	cleanup_all_session_xauthfile();
++#endif
++
+ 	/*
+ 	 * Cleanup ptys/utmp only if privsep is disabled,
+ 	 * or if running in monitor.
+--- orig/session.h	Thu Jul 30 10:35:12 2015
++++ new/session.h	Tue Aug  4 11:30:04 2015
+@@ -49,6 +49,9 @@
+ 	char	*auth_display;
+ 	char	*auth_proto;
+ 	char	*auth_data;
++#ifdef PER_SESSION_XAUTHFILE
++	char    *auth_file;	/* xauth(1) authority file */
++#endif
+ 	int	single_connection;
+ 
+ 	/* proto 2 */