unleashed-userland README
[unleashed-userland.git] / components / network / openssh / patches / 0019-Per-session-xauthfile.patch
blobffbc70fecf0aa18c11693b2590720a9c722596f1
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
7 is read-only.
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.
13 ---
14 session.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
15 session.h | 3 ++
16 2 files changed, 137 insertions(+), 4 deletions(-)
18 diff --git a/session.c b/session.c
19 index 87fddfc..36f8c62 100644
20 --- a/session.c
21 +++ b/session.c
22 @@ -63,6 +63,10 @@
23 #include <unistd.h>
24 #include <limits.h>
26 +#ifdef PER_SESSION_XAUTHFILE
27 +#include <libgen.h>
28 +#endif
30 #include "openbsd-compat/sys-queue.h"
31 #include "xmalloc.h"
32 #include "ssh.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();
40 +#endif
42 /* import */
43 extern ServerOptions options;
44 extern char *__progname;
45 @@ -1242,6 +1251,11 @@ do_setup_env(Session *s, const char *shell)
46 if (getenv("TZ"))
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);
52 +#endif
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)
59 int success;
61 +#ifdef PER_SESSION_XAUTHFILE
62 + int fd;
63 + char xauthdir[] = "/tmp/ssh-xauth-XXXXXX";
64 +#endif
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();
71 packet_check_eom();
73 - if (xauth_valid_string(s->auth_proto) &&
74 - xauth_valid_string(s->auth_data))
75 - success = session_setup_x11fwd(s);
76 - else {
77 + if (!xauth_valid_string(s->auth_proto) ||
78 + !xauth_valid_string(s->auth_data)) {
79 success = 0;
80 error("Invalid X11 forwarding data");
81 + goto out;
82 + }
84 +#ifdef PER_SESSION_XAUTHFILE
85 + /*
86 + * Create per session X authority file in the /tmp directory.
87 + *
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.
91 + */
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");
98 + success = 0;
99 + goto out;
101 + /*
102 + * we don't want that "creating new authority file" message to
103 + * be printed by xauth(1) so we must create that file
104 + * beforehand.
105 + */
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));
117 + } else {
118 + if (close(fd) != 0) {
119 + error("close() failed on temporary X authority "
120 + "file: %s", strerror(errno));
121 + success = 0;
122 + goto out;
124 + debug("temporary X authority file %s created",
125 + s->auth_file);
126 + debug("session number = %d", s->self);
128 + } else {
129 + error("failed to create a directory for the temporary X "
130 + "authority file: %.100s; will use the default xauth file",
131 + strerror(errno));
133 +#endif
135 + success = session_setup_x11fwd(s);
137 +out:
138 if (!success) {
139 free(s->auth_proto);
140 free(s->auth_data);
141 s->auth_proto = NULL;
142 s->auth_data = NULL;
143 +#ifdef PER_SESSION_XAUTHFILE
144 + free(s->auth_file);
145 + s->auth_file = NULL;
146 +#endif
149 return success;
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.
160 + */
161 +void
162 +session_xauthfile_cleanup(Session *s)
164 + if (s == NULL || s->auth_file == NULL) {
165 + return;
168 + debug("session_xauthfile_cleanup: session %d removing %s", s->self,
169 + s->auth_file);
171 + if (unlink(s->auth_file) == -1) {
172 + error("session_xauthfile_cleanup: cannot remove xauth file "
173 + "%s: %.100s", s->auth_file, strerror(errno));
174 + return;
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));
182 + return;
184 + free(s->auth_file);
185 + s->auth_file = NULL;
189 + * This is called by do_cleanup() when cleanup_exit() is called.
190 + */
191 +void
192 +cleanup_all_session_xauthfile()
194 + int i;
195 + for (i = 0; i < sessions_nalloc; i++) {
196 + session_xauthfile_cleanup(&sessions[i]);
199 +#endif
201 static char *
202 sig2name(int sig)
204 @@ -2542,6 +2665,9 @@ session_close(Session *s)
205 free(s->auth_display);
206 free(s->auth_data);
207 free(s->auth_proto);
208 +#ifdef PER_SESSION_XAUTHFILE
209 + session_xauthfile_cleanup(s);
210 +#endif
211 free(s->subsys);
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();
220 +#endif
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
227 --- a/session.h
228 +++ b/session.h
229 @@ -49,6 +49,9 @@ struct Session {
230 char *auth_display;
231 char *auth_proto;
232 char *auth_data;
233 +#ifdef PER_SESSION_XAUTHFILE
234 + char *auth_file; /* xauth(1) authority file */
235 +#endif
236 int single_connection;
238 /* proto 2 */
240 2.5.4 (Apple Git-61)