1 From a0027fbda837126e12d04098019a133ea83a9b75 Mon Sep 17 00:00:00 2001
2 From: oracle <solaris@oracle.com>
3 Date: Tue, 22 Dec 2015 17:12:50 -0800
4 Subject: [PATCH 19/34] Per-session xauthfile
6 This patch is to fix a X11 connection failure when a user's home directory
9 We have contributed back this fix to the OpenSSH upstream community. For
10 more information, see https://bugzilla.mindrot.org/show_bug.cgi?id=2440
11 In the future, if this fix is accepted by the upsteam in a later release, we
12 will remove this patch when we upgrade to that release.
14 session.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
16 2 files changed, 137 insertions(+), 4 deletions(-)
18 diff --git a/session.c b/session.c
19 index 87fddfc..36f8c62 100644
26 +#ifdef PER_SESSION_XAUTHFILE
30 #include "openbsd-compat/sys-queue.h"
33 @@ -133,6 +137,11 @@ static void do_authenticated2(Authctxt *);
35 static int session_pty_req(Session *);
37 +#ifdef PER_SESSION_XAUTHFILE
38 +void session_xauthfile_cleanup(Session *);
39 +void cleanup_all_session_xauthfile();
43 extern ServerOptions options;
44 extern char *__progname;
45 @@ -1242,6 +1251,11 @@ do_setup_env(Session *s, const char *shell)
47 child_set_env(&env, &envsize, "TZ", getenv("TZ"));
49 +#ifdef PER_SESSION_XAUTHFILE
50 + if (s->auth_file != NULL)
51 + child_set_env(&env, &envsize, "XAUTHORITY", s->auth_file);
54 /* Set custom environment options from RSA authentication. */
55 if (!options.use_login) {
56 while (custom_environment) {
57 @@ -2189,6 +2203,11 @@ session_x11_req(Session *s)
61 +#ifdef PER_SESSION_XAUTHFILE
63 + char xauthdir[] = "/tmp/ssh-xauth-XXXXXX";
66 if (s->auth_proto != NULL || s->auth_data != NULL) {
67 error("session_x11_req: session %d: "
68 "x11 forwarding already active", s->self);
69 @@ -2200,19 +2219,78 @@ session_x11_req(Session *s)
70 s->screen = packet_get_int();
73 - if (xauth_valid_string(s->auth_proto) &&
74 - xauth_valid_string(s->auth_data))
75 - success = session_setup_x11fwd(s);
77 + if (!xauth_valid_string(s->auth_proto) ||
78 + !xauth_valid_string(s->auth_data)) {
80 error("Invalid X11 forwarding data");
84 +#ifdef PER_SESSION_XAUTHFILE
86 + * Create per session X authority file in the /tmp directory.
88 + * If mkdtemp() or open() fails then s->auth_file remains NULL which
89 + * means that we won't set XAUTHORITY variable in child's environment
90 + * and xauth(1) will use the default location for the authority file.
92 + if (mkdtemp(xauthdir) != NULL) {
93 + s->auth_file = xmalloc(MAXPATHLEN);
94 + if (snprintf(s->auth_file, MAXPATHLEN, "%s/xauthfile",
95 + xauthdir) >= MAXPATHLEN) {
96 + error("temporary X authority file name was too long "
97 + "for the buffer allocated");
102 + * we don't want that "creating new authority file" message to
103 + * be printed by xauth(1) so we must create that file
106 + if ((fd = open(s->auth_file, O_CREAT | O_EXCL | O_RDONLY,
107 + S_IRUSR | S_IWUSR)) == -1) {
108 + error("failed to create the temporary X authority "
109 + "file %s: %.100s; will use the default one",
110 + s->auth_file, strerror(errno));
111 + free(s->auth_file);
112 + s->auth_file = NULL;
113 + if (rmdir(xauthdir) == -1) {
114 + error("cannot remove xauth directory "
115 + "%s: %.100s", xauthdir, strerror(errno));
118 + if (close(fd) != 0) {
119 + error("close() failed on temporary X authority "
120 + "file: %s", strerror(errno));
124 + debug("temporary X authority file %s created",
126 + debug("session number = %d", s->self);
129 + error("failed to create a directory for the temporary X "
130 + "authority file: %.100s; will use the default xauth file",
135 + success = session_setup_x11fwd(s);
141 s->auth_proto = NULL;
143 +#ifdef PER_SESSION_XAUTHFILE
144 + free(s->auth_file);
145 + s->auth_file = NULL;
152 @@ -2403,6 +2481,51 @@ session_pty_cleanup(Session *s)
153 PRIVSEP(session_pty_cleanup2(s));
156 +#ifdef PER_SESSION_XAUTHFILE
158 + * We use a different temporary X authority file per session so we should
159 + * remove those files when cleanup_exit() is called.
162 +session_xauthfile_cleanup(Session *s)
164 + if (s == NULL || s->auth_file == NULL) {
168 + debug("session_xauthfile_cleanup: session %d removing %s", s->self,
171 + if (unlink(s->auth_file) == -1) {
172 + error("session_xauthfile_cleanup: cannot remove xauth file "
173 + "%s: %.100s", s->auth_file, strerror(errno));
177 + /* dirname() will modify s->auth_file but that's ok */
178 + if (rmdir(dirname(s->auth_file)) == -1) {
179 + error("session_xauthfile_cleanup: "
180 + "cannot remove xauth directory %s: %.100s",
181 + s->auth_file, strerror(errno));
184 + free(s->auth_file);
185 + s->auth_file = NULL;
189 + * This is called by do_cleanup() when cleanup_exit() is called.
192 +cleanup_all_session_xauthfile()
195 + for (i = 0; i < sessions_nalloc; i++) {
196 + session_xauthfile_cleanup(&sessions[i]);
204 @@ -2542,6 +2665,9 @@ session_close(Session *s)
205 free(s->auth_display);
208 +#ifdef PER_SESSION_XAUTHFILE
209 + session_xauthfile_cleanup(s);
212 if (s->env != NULL) {
213 for (i = 0; i < s->num_env; i++) {
214 @@ -2793,6 +2919,10 @@ do_cleanup(Authctxt *authctxt)
215 /* remove agent socket */
216 auth_sock_cleanup_proc(authctxt->pw);
218 +#ifdef PER_SESSION_XAUTHFILE
219 + cleanup_all_session_xauthfile();
223 * Cleanup ptys/utmp only if privsep is disabled,
224 * or if running in monitor.
225 diff --git a/session.h b/session.h
226 index 6a2f35e..276cd04 100644
229 @@ -49,6 +49,9 @@ struct Session {
233 +#ifdef PER_SESSION_XAUTHFILE
234 + char *auth_file; /* xauth(1) authority file */
236 int single_connection;