components/openssh/patches/031-per_session_xauthfile.patch
author Jan Parcel <jan.parcel@oracle.com>
Mon, 25 Jan 2016 10:57:40 -0800
branchs11u3-sru
changeset 5324 5683175b6e99
child 5613 27ea636da8ce
permissions -rw-r--r--
PSARC/2015/395 OpenSSH 7.1p1 PSARC 2014/390 OpenSSH GSSKEY 21696247 upgrade OpenSSH to 7.1p1 22031540 problem in UTILITY/OPENSSH 22022180 problem in UTILITY/OPENSSH 22048638 problem in UTILITY/OPENSSH 19775805 OpenSSH contains a redundant call to do_pam_setcred() 21379157 OpenSSH shouldn't call setproject(3PROJECT) when configured to use PAM 20919294 upgrade OpenSSH to 6.8p1 19130869 migrate the Xforwarding bug fix (15350344) from SunSSH to OpenSSH 21861322 OpenSSH client hangs on broken pipe 22018764 remove cast128-cbc from OpenSSH 21919790 add GSSKeyEx as an alias to GSSAPIKeyExchange in OpenSSH 19941148 GSS-API Key Exchange for OpenSSH 21643415 OpenSSH should use AI_ADDRCONFIG per bug 19827438 20370803 OpenSSH patch number collision 20711463 OpenSSH wants to be able to login to a role too 22389801 OpenSSH: remove cast from ssh(1), sshd(8), ssh_config(5) and sshd_config(5) 22582153 openssh system/linker should be added to core REQ

#
# 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 */