rev |
line source |
al@20905
|
1 From ea544ffc18405237ccd95d28d7f45afef49aca17 Mon Sep 17 00:00:00 2001
|
al@20905
|
2 From: Colin Walters <walters@redhat.com>
|
al@20905
|
3 Date: Thu, 4 Jun 2015 12:15:18 -0400
|
al@20905
|
4 Subject: CVE-2015-4625: Use unpredictable cookie values, keep them secret
|
al@20905
|
5 MIME-Version: 1.0
|
al@20905
|
6 Content-Type: text/plain; charset=UTF-8
|
al@20905
|
7 Content-Transfer-Encoding: 8bit
|
al@20905
|
8
|
al@20905
|
9 Tavis noted that it'd be possible with a 32 bit counter for someone to
|
al@20905
|
10 cause the cookie to wrap by creating Authentication requests in a
|
al@20905
|
11 loop.
|
al@20905
|
12
|
al@20905
|
13 Something important to note here is that wrapping of signed integers
|
al@20905
|
14 is undefined behavior in C, so we definitely want to fix that. All
|
al@20905
|
15 counter integers used in this patch are unsigned.
|
al@20905
|
16
|
al@20905
|
17 See the comment above `authentication_agent_generate_cookie` for
|
al@20905
|
18 details, but basically we're now using a cookie of the form:
|
al@20905
|
19
|
al@20905
|
20 ```
|
al@20905
|
21 <agent serial> - <agent random id> - <session serial> - <session
|
al@20905
|
22 random id>
|
al@20905
|
23 ```
|
al@20905
|
24
|
al@20905
|
25 Which has multiple 64 bit counters, plus unpredictable random 128 bit
|
al@20905
|
26 integer ids (effectively UUIDs, but we're not calling them that
|
al@20905
|
27 because we don't need to be globally unique.
|
al@20905
|
28
|
al@20905
|
29 We further ensure that the cookies are not visible to other processes
|
al@20905
|
30 by changing the setuid helper to accept them over standard input. This
|
al@20905
|
31 means that an attacker would have to guess both ids.
|
al@20905
|
32
|
al@20905
|
33 In any case, the security hole here is better fixed with the other
|
al@20905
|
34 change to bind user id (uid) of the agent with cookie lookups, making
|
al@20905
|
35 cookie guessing worthless.
|
al@20905
|
36
|
al@20905
|
37 Nevertheless, I think it's worth doing this change too, for defense in
|
al@20905
|
38 depth.
|
al@20905
|
39
|
al@20905
|
40 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=90832
|
al@20905
|
41 CVE: CVE-2015-4625
|
al@20905
|
42 Reported-by: Tavis Ormandy <taviso@google.com>
|
al@20905
|
43 Reviewed-by: Miloslav Trmač <mitr@redhat.com>
|
al@20905
|
44 Signed-off-by: Colin Walters <walters@redhat.com>
|
al@20905
|
45
|
al@20905
|
46 diff --git a/src/polkitagent/polkitagenthelper-pam.c b/src/polkitagent/polkitagenthelper-pam.c
|
al@20905
|
47 index 937386e..19062aa 100644
|
al@20905
|
48 --- a/src/polkitagent/polkitagenthelper-pam.c
|
al@20905
|
49 +++ b/src/polkitagent/polkitagenthelper-pam.c
|
al@20905
|
50 @@ -65,7 +65,7 @@ main (int argc, char *argv[])
|
al@20905
|
51 {
|
al@20905
|
52 int rc;
|
al@20905
|
53 const char *user_to_auth;
|
al@20905
|
54 - const char *cookie;
|
al@20905
|
55 + char *cookie = NULL;
|
al@20905
|
56 struct pam_conv pam_conversation;
|
al@20905
|
57 pam_handle_t *pam_h;
|
al@20905
|
58 const void *authed_user;
|
al@20905
|
59 @@ -97,7 +97,7 @@ main (int argc, char *argv[])
|
al@20905
|
60 openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
|
al@20905
|
61
|
al@20905
|
62 /* check for correct invocation */
|
al@20905
|
63 - if (argc != 3)
|
al@20905
|
64 + if (!(argc == 2 || argc == 3))
|
al@20905
|
65 {
|
al@20905
|
66 syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
|
al@20905
|
67 fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n");
|
al@20905
|
68 @@ -105,7 +105,10 @@ main (int argc, char *argv[])
|
al@20905
|
69 }
|
al@20905
|
70
|
al@20905
|
71 user_to_auth = argv[1];
|
al@20905
|
72 - cookie = argv[2];
|
al@20905
|
73 +
|
al@20905
|
74 + cookie = read_cookie (argc, argv);
|
al@20905
|
75 + if (!cookie)
|
al@20905
|
76 + goto error;
|
al@20905
|
77
|
al@20905
|
78 if (getuid () != 0)
|
al@20905
|
79 {
|
al@20905
|
80 @@ -203,6 +206,8 @@ main (int argc, char *argv[])
|
al@20905
|
81 goto error;
|
al@20905
|
82 }
|
al@20905
|
83
|
al@20905
|
84 + free (cookie);
|
al@20905
|
85 +
|
al@20905
|
86 #ifdef PAH_DEBUG
|
al@20905
|
87 fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n");
|
al@20905
|
88 #endif /* PAH_DEBUG */
|
al@20905
|
89 @@ -212,6 +217,7 @@ main (int argc, char *argv[])
|
al@20905
|
90 return 0;
|
al@20905
|
91
|
al@20905
|
92 error:
|
al@20905
|
93 + free (cookie);
|
al@20905
|
94 if (pam_h != NULL)
|
al@20905
|
95 pam_end (pam_h, rc);
|
al@20905
|
96
|
al@20905
|
97 diff --git a/src/polkitagent/polkitagenthelper-shadow.c b/src/polkitagent/polkitagenthelper-shadow.c
|
al@20905
|
98 index a4f73ac..e877915 100644
|
al@20905
|
99 --- a/src/polkitagent/polkitagenthelper-shadow.c
|
al@20905
|
100 +++ b/src/polkitagent/polkitagenthelper-shadow.c
|
al@20905
|
101 @@ -46,7 +46,7 @@ main (int argc, char *argv[])
|
al@20905
|
102 {
|
al@20905
|
103 struct spwd *shadow;
|
al@20905
|
104 const char *user_to_auth;
|
al@20905
|
105 - const char *cookie;
|
al@20905
|
106 + char *cookie = NULL;
|
al@20905
|
107 time_t now;
|
al@20905
|
108
|
al@20905
|
109 /* clear the entire environment to avoid attacks with
|
al@20905
|
110 @@ -67,7 +67,7 @@ main (int argc, char *argv[])
|
al@20905
|
111 openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
|
al@20905
|
112
|
al@20905
|
113 /* check for correct invocation */
|
al@20905
|
114 - if (argc != 3)
|
al@20905
|
115 + if (!(argc == 2 || argc == 3))
|
al@20905
|
116 {
|
al@20905
|
117 syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
|
al@20905
|
118 fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n");
|
al@20905
|
119 @@ -86,7 +86,10 @@ main (int argc, char *argv[])
|
al@20905
|
120 }
|
al@20905
|
121
|
al@20905
|
122 user_to_auth = argv[1];
|
al@20905
|
123 - cookie = argv[2];
|
al@20905
|
124 +
|
al@20905
|
125 + cookie = read_cookie (argc, argv);
|
al@20905
|
126 + if (!cookie)
|
al@20905
|
127 + goto error;
|
al@20905
|
128
|
al@20905
|
129 #ifdef PAH_DEBUG
|
al@20905
|
130 fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth);
|
al@20905
|
131 @@ -153,6 +156,8 @@ main (int argc, char *argv[])
|
al@20905
|
132 goto error;
|
al@20905
|
133 }
|
al@20905
|
134
|
al@20905
|
135 + free (cookie);
|
al@20905
|
136 +
|
al@20905
|
137 #ifdef PAH_DEBUG
|
al@20905
|
138 fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n");
|
al@20905
|
139 #endif /* PAH_DEBUG */
|
al@20905
|
140 @@ -162,6 +167,7 @@ main (int argc, char *argv[])
|
al@20905
|
141 return 0;
|
al@20905
|
142
|
al@20905
|
143 error:
|
al@20905
|
144 + free (cookie);
|
al@20905
|
145 fprintf (stdout, "FAILURE\n");
|
al@20905
|
146 flush_and_wait ();
|
al@20905
|
147 return 1;
|
al@20905
|
148 diff --git a/src/polkitagent/polkitagenthelperprivate.c b/src/polkitagent/polkitagenthelperprivate.c
|
al@20905
|
149 index cfa77fc..e23f9f5 100644
|
al@20905
|
150 --- a/src/polkitagent/polkitagenthelperprivate.c
|
al@20905
|
151 +++ b/src/polkitagent/polkitagenthelperprivate.c
|
al@20905
|
152 @@ -23,6 +23,7 @@
|
al@20905
|
153 #include "config.h"
|
al@20905
|
154 #include "polkitagenthelperprivate.h"
|
al@20905
|
155 #include <stdio.h>
|
al@20905
|
156 +#include <string.h>
|
al@20905
|
157 #include <stdlib.h>
|
al@20905
|
158 #include <unistd.h>
|
al@20905
|
159
|
al@20905
|
160 @@ -45,6 +46,38 @@ _polkit_clearenv (void)
|
al@20905
|
161 #endif
|
al@20905
|
162
|
al@20905
|
163
|
al@20905
|
164 +char *
|
al@20905
|
165 +read_cookie (int argc, char **argv)
|
al@20905
|
166 +{
|
al@20905
|
167 + /* As part of CVE-2015-4625, we started passing the cookie
|
al@20905
|
168 + * on standard input, to ensure it's not visible to other
|
al@20905
|
169 + * processes. However, to ensure that things continue
|
al@20905
|
170 + * to work if the setuid binary is upgraded while old
|
al@20905
|
171 + * agents are still running (this will be common with
|
al@20905
|
172 + * package managers), we support both modes.
|
al@20905
|
173 + */
|
al@20905
|
174 + if (argc == 3)
|
al@20905
|
175 + return strdup (argv[2]);
|
al@20905
|
176 + else
|
al@20905
|
177 + {
|
al@20905
|
178 + char *ret = NULL;
|
al@20905
|
179 + size_t n = 0;
|
al@20905
|
180 + ssize_t r = getline (&ret, &n, stdin);
|
al@20905
|
181 + if (r == -1)
|
al@20905
|
182 + {
|
al@20905
|
183 + if (!feof (stdin))
|
al@20905
|
184 + perror ("getline");
|
al@20905
|
185 + free (ret);
|
al@20905
|
186 + return NULL;
|
al@20905
|
187 + }
|
al@20905
|
188 + else
|
al@20905
|
189 + {
|
al@20905
|
190 + g_strchomp (ret);
|
al@20905
|
191 + return ret;
|
al@20905
|
192 + }
|
al@20905
|
193 + }
|
al@20905
|
194 +}
|
al@20905
|
195 +
|
al@20905
|
196 gboolean
|
al@20905
|
197 send_dbus_message (const char *cookie, const char *user)
|
al@20905
|
198 {
|
al@20905
|
199 diff --git a/src/polkitagent/polkitagenthelperprivate.h b/src/polkitagent/polkitagenthelperprivate.h
|
al@20905
|
200 index aeca2c7..547fdcc 100644
|
al@20905
|
201 --- a/src/polkitagent/polkitagenthelperprivate.h
|
al@20905
|
202 +++ b/src/polkitagent/polkitagenthelperprivate.h
|
al@20905
|
203 @@ -38,6 +38,8 @@
|
al@20905
|
204
|
al@20905
|
205 int _polkit_clearenv (void);
|
al@20905
|
206
|
al@20905
|
207 +char *read_cookie (int argc, char **argv);
|
al@20905
|
208 +
|
al@20905
|
209 gboolean send_dbus_message (const char *cookie, const char *user);
|
al@20905
|
210
|
al@20905
|
211 void flush_and_wait ();
|
al@20905
|
212 diff --git a/src/polkitagent/polkitagentsession.c b/src/polkitagent/polkitagentsession.c
|
al@20905
|
213 index f014773..8b93ad0 100644
|
al@20905
|
214 --- a/src/polkitagent/polkitagentsession.c
|
al@20905
|
215 +++ b/src/polkitagent/polkitagentsession.c
|
al@20905
|
216 @@ -55,6 +55,7 @@
|
al@20905
|
217 #include <stdio.h>
|
al@20905
|
218 #include <sys/types.h>
|
al@20905
|
219 #include <sys/wait.h>
|
al@20905
|
220 +#include <gio/gunixoutputstream.h>
|
al@20905
|
221 #include <pwd.h>
|
al@20905
|
222
|
al@20905
|
223 #include "polkitagentmarshal.h"
|
al@20905
|
224 @@ -88,7 +89,7 @@ struct _PolkitAgentSession
|
al@20905
|
225 gchar *cookie;
|
al@20905
|
226 PolkitIdentity *identity;
|
al@20905
|
227
|
al@20905
|
228 - int child_stdin;
|
al@20905
|
229 + GOutputStream *child_stdin;
|
al@20905
|
230 int child_stdout;
|
al@20905
|
231 GPid child_pid;
|
al@20905
|
232
|
al@20905
|
233 @@ -129,7 +130,6 @@ G_DEFINE_TYPE (PolkitAgentSession, polkit_agent_session, G_TYPE_OBJECT);
|
al@20905
|
234 static void
|
al@20905
|
235 polkit_agent_session_init (PolkitAgentSession *session)
|
al@20905
|
236 {
|
al@20905
|
237 - session->child_stdin = -1;
|
al@20905
|
238 session->child_stdout = -1;
|
al@20905
|
239 }
|
al@20905
|
240
|
al@20905
|
241 @@ -395,11 +395,7 @@ kill_helper (PolkitAgentSession *session)
|
al@20905
|
242 session->child_stdout = -1;
|
al@20905
|
243 }
|
al@20905
|
244
|
al@20905
|
245 - if (session->child_stdin != -1)
|
al@20905
|
246 - {
|
al@20905
|
247 - g_warn_if_fail (close (session->child_stdin) == 0);
|
al@20905
|
248 - session->child_stdin = -1;
|
al@20905
|
249 - }
|
al@20905
|
250 + g_clear_object (&session->child_stdin);
|
al@20905
|
251
|
al@20905
|
252 session->helper_is_running = FALSE;
|
al@20905
|
253
|
al@20905
|
254 @@ -545,9 +541,9 @@ polkit_agent_session_response (PolkitAgentSession *session,
|
al@20905
|
255
|
al@20905
|
256 add_newline = (response[response_len] != '\n');
|
al@20905
|
257
|
al@20905
|
258 - write (session->child_stdin, response, response_len);
|
al@20905
|
259 + (void) g_output_stream_write_all (session->child_stdin, response, response_len, NULL, NULL, NULL);
|
al@20905
|
260 if (add_newline)
|
al@20905
|
261 - write (session->child_stdin, newline, 1);
|
al@20905
|
262 + (void) g_output_stream_write_all (session->child_stdin, newline, 1, NULL, NULL, NULL);
|
al@20905
|
263 }
|
al@20905
|
264
|
al@20905
|
265 /**
|
al@20905
|
266 @@ -567,8 +563,9 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
|
al@20905
|
267 {
|
al@20905
|
268 uid_t uid;
|
al@20905
|
269 GError *error;
|
al@20905
|
270 - gchar *helper_argv[4];
|
al@20905
|
271 + gchar *helper_argv[3];
|
al@20905
|
272 struct passwd *passwd;
|
al@20905
|
273 + int stdin_fd = -1;
|
al@20905
|
274
|
al@20905
|
275 g_return_if_fail (POLKIT_AGENT_IS_SESSION (session));
|
al@20905
|
276
|
al@20905
|
277 @@ -600,10 +597,8 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
|
al@20905
|
278
|
al@20905
|
279 helper_argv[0] = PACKAGE_PREFIX "/lib/polkit-1/polkit-agent-helper-1";
|
al@20905
|
280 helper_argv[1] = passwd->pw_name;
|
al@20905
|
281 - helper_argv[2] = session->cookie;
|
al@20905
|
282 - helper_argv[3] = NULL;
|
al@20905
|
283 + helper_argv[2] = NULL;
|
al@20905
|
284
|
al@20905
|
285 - session->child_stdin = -1;
|
al@20905
|
286 session->child_stdout = -1;
|
al@20905
|
287
|
al@20905
|
288 error = NULL;
|
al@20905
|
289 @@ -615,7 +610,7 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
|
al@20905
|
290 NULL,
|
al@20905
|
291 NULL,
|
al@20905
|
292 &session->child_pid,
|
al@20905
|
293 - &session->child_stdin,
|
al@20905
|
294 + &stdin_fd,
|
al@20905
|
295 &session->child_stdout,
|
al@20905
|
296 NULL,
|
al@20905
|
297 &error))
|
al@20905
|
298 @@ -628,6 +623,13 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
|
al@20905
|
299 if (G_UNLIKELY (_show_debug ()))
|
al@20905
|
300 g_print ("PolkitAgentSession: spawned helper with pid %d\n", (gint) session->child_pid);
|
al@20905
|
301
|
al@20905
|
302 + session->child_stdin = (GOutputStream*)g_unix_output_stream_new (stdin_fd, TRUE);
|
al@20905
|
303 +
|
al@20905
|
304 + /* Write the cookie on stdin so it can't be seen by other processes */
|
al@20905
|
305 + (void) g_output_stream_write_all (session->child_stdin, session->cookie, strlen (session->cookie),
|
al@20905
|
306 + NULL, NULL, NULL);
|
al@20905
|
307 + (void) g_output_stream_write_all (session->child_stdin, "\n", 1, NULL, NULL, NULL);
|
al@20905
|
308 +
|
al@20905
|
309 session->child_stdout_channel = g_io_channel_unix_new (session->child_stdout);
|
al@20905
|
310 session->child_stdout_watch_source = g_io_create_watch (session->child_stdout_channel,
|
al@20905
|
311 G_IO_IN | G_IO_ERR | G_IO_HUP);
|
al@20905
|
312 diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
|
al@20905
|
313 index 3f339e9..15adc6a 100644
|
al@20905
|
314 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c
|
al@20905
|
315 +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
|
al@20905
|
316 @@ -214,6 +214,8 @@ typedef struct
|
al@20905
|
317
|
al@20905
|
318 GDBusConnection *system_bus_connection;
|
al@20905
|
319 guint name_owner_changed_signal_id;
|
al@20905
|
320 +
|
al@20905
|
321 + guint64 agent_serial;
|
al@20905
|
322 } PolkitBackendInteractiveAuthorityPrivate;
|
al@20905
|
323
|
al@20905
|
324 /* ---------------------------------------------------------------------------------------------------- */
|
al@20905
|
325 @@ -439,11 +441,15 @@ struct AuthenticationAgent
|
al@20905
|
326 volatile gint ref_count;
|
al@20905
|
327
|
al@20905
|
328 PolkitSubject *scope;
|
al@20905
|
329 + guint64 serial;
|
al@20905
|
330
|
al@20905
|
331 gchar *locale;
|
al@20905
|
332 GVariant *registration_options;
|
al@20905
|
333 gchar *object_path;
|
al@20905
|
334 gchar *unique_system_bus_name;
|
al@20905
|
335 + GRand *cookie_pool;
|
al@20905
|
336 + gchar *cookie_prefix;
|
al@20905
|
337 + guint64 cookie_serial;
|
al@20905
|
338
|
al@20905
|
339 GDBusProxy *proxy;
|
al@20905
|
340
|
al@20905
|
341 @@ -1427,9 +1433,54 @@ authentication_session_cancelled_cb (GCancellable *cancellable,
|
al@20905
|
342 authentication_session_cancel (session);
|
al@20905
|
343 }
|
al@20905
|
344
|
al@20905
|
345 +/* We're not calling this a UUID, but it's basically
|
al@20905
|
346 + * the same thing, just not formatted that way because:
|
al@20905
|
347 + *
|
al@20905
|
348 + * - I'm too lazy to do it
|
al@20905
|
349 + * - If we did, people might think it was actually
|
al@20905
|
350 + * generated from /dev/random, which we're not doing
|
al@20905
|
351 + * because this value doesn't actually need to be
|
al@20905
|
352 + * globally unique.
|
al@20905
|
353 + */
|
al@20905
|
354 +static void
|
al@20905
|
355 +append_rand_u128_str (GString *buf,
|
al@20905
|
356 + GRand *pool)
|
al@20905
|
357 +{
|
al@20905
|
358 + g_string_append_printf (buf, "%08x%08x%08x%08x",
|
al@20905
|
359 + g_rand_int (pool),
|
al@20905
|
360 + g_rand_int (pool),
|
al@20905
|
361 + g_rand_int (pool),
|
al@20905
|
362 + g_rand_int (pool));
|
al@20905
|
363 +}
|
al@20905
|
364 +
|
al@20905
|
365 +/* A value that should be unique to the (AuthenticationAgent, AuthenticationSession)
|
al@20905
|
366 + * pair, and not guessable by other agents.
|
al@20905
|
367 + *
|
al@20905
|
368 + * <agent serial> - <agent uuid> - <session serial> - <session uuid>
|
al@20905
|
369 + *
|
al@20905
|
370 + * See http://lists.freedesktop.org/archives/polkit-devel/2015-June/000425.html
|
al@20905
|
371 + *
|
al@20905
|
372 + */
|
al@20905
|
373 +static gchar *
|
al@20905
|
374 +authentication_agent_generate_cookie (AuthenticationAgent *agent)
|
al@20905
|
375 +{
|
al@20905
|
376 + GString *buf = g_string_new ("");
|
al@20905
|
377 +
|
al@20905
|
378 + g_string_append (buf, agent->cookie_prefix);
|
al@20905
|
379 +
|
al@20905
|
380 + g_string_append_c (buf, '-');
|
al@20905
|
381 + agent->cookie_serial++;
|
al@20905
|
382 + g_string_append_printf (buf, "%" G_GUINT64_FORMAT,
|
al@20905
|
383 + agent->cookie_serial);
|
al@20905
|
384 + g_string_append_c (buf, '-');
|
al@20905
|
385 + append_rand_u128_str (buf, agent->cookie_pool);
|
al@20905
|
386 +
|
al@20905
|
387 + return g_string_free (buf, FALSE);
|
al@20905
|
388 +}
|
al@20905
|
389 +
|
al@20905
|
390 +
|
al@20905
|
391 static AuthenticationSession *
|
al@20905
|
392 authentication_session_new (AuthenticationAgent *agent,
|
al@20905
|
393 - const gchar *cookie,
|
al@20905
|
394 PolkitSubject *subject,
|
al@20905
|
395 PolkitIdentity *user_of_subject,
|
al@20905
|
396 PolkitSubject *caller,
|
al@20905
|
397 @@ -1447,7 +1498,7 @@ authentication_session_new (AuthenticationAgent *agent,
|
al@20905
|
398
|
al@20905
|
399 session = g_new0 (AuthenticationSession, 1);
|
al@20905
|
400 session->agent = authentication_agent_ref (agent);
|
al@20905
|
401 - session->cookie = g_strdup (cookie);
|
al@20905
|
402 + session->cookie = authentication_agent_generate_cookie (agent);
|
al@20905
|
403 session->subject = g_object_ref (subject);
|
al@20905
|
404 session->user_of_subject = g_object_ref (user_of_subject);
|
al@20905
|
405 session->caller = g_object_ref (caller);
|
al@20905
|
406 @@ -1496,16 +1547,6 @@ authentication_session_free (AuthenticationSession *session)
|
al@20905
|
407 g_free (session);
|
al@20905
|
408 }
|
al@20905
|
409
|
al@20905
|
410 -static gchar *
|
al@20905
|
411 -authentication_agent_new_cookie (AuthenticationAgent *agent)
|
al@20905
|
412 -{
|
al@20905
|
413 - static gint counter = 0;
|
al@20905
|
414 -
|
al@20905
|
415 - /* TODO: use a more random-looking cookie */
|
al@20905
|
416 -
|
al@20905
|
417 - return g_strdup_printf ("cookie%d", counter++);
|
al@20905
|
418 -}
|
al@20905
|
419 -
|
al@20905
|
420 static PolkitSubject *
|
al@20905
|
421 authentication_agent_get_scope (AuthenticationAgent *agent)
|
al@20905
|
422 {
|
al@20905
|
423 @@ -1553,12 +1594,15 @@ authentication_agent_unref (AuthenticationAgent *agent)
|
al@20905
|
424 g_free (agent->unique_system_bus_name);
|
al@20905
|
425 if (agent->registration_options != NULL)
|
al@20905
|
426 g_variant_unref (agent->registration_options);
|
al@20905
|
427 + g_rand_free (agent->cookie_pool);
|
al@20905
|
428 + g_free (agent->cookie_prefix);
|
al@20905
|
429 g_free (agent);
|
al@20905
|
430 }
|
al@20905
|
431 }
|
al@20905
|
432
|
al@20905
|
433 static AuthenticationAgent *
|
al@20905
|
434 -authentication_agent_new (PolkitSubject *scope,
|
al@20905
|
435 +authentication_agent_new (guint64 serial,
|
al@20905
|
436 + PolkitSubject *scope,
|
al@20905
|
437 const gchar *unique_system_bus_name,
|
al@20905
|
438 const gchar *locale,
|
al@20905
|
439 const gchar *object_path,
|
al@20905
|
440 @@ -1592,6 +1636,7 @@ authentication_agent_new (PolkitSubject *scope,
|
al@20905
|
441
|
al@20905
|
442 agent = g_new0 (AuthenticationAgent, 1);
|
al@20905
|
443 agent->ref_count = 1;
|
al@20905
|
444 + agent->serial = serial;
|
al@20905
|
445 agent->scope = g_object_ref (scope);
|
al@20905
|
446 agent->object_path = g_strdup (object_path);
|
al@20905
|
447 agent->unique_system_bus_name = g_strdup (unique_system_bus_name);
|
al@20905
|
448 @@ -1599,6 +1644,25 @@ authentication_agent_new (PolkitSubject *scope,
|
al@20905
|
449 agent->registration_options = registration_options != NULL ? g_variant_ref (registration_options) : NULL;
|
al@20905
|
450 agent->proxy = proxy;
|
al@20905
|
451
|
al@20905
|
452 + {
|
al@20905
|
453 + GString *cookie_prefix = g_string_new ("");
|
al@20905
|
454 + GRand *agent_private_rand = g_rand_new ();
|
al@20905
|
455 +
|
al@20905
|
456 + g_string_append_printf (cookie_prefix, "%" G_GUINT64_FORMAT "-", agent->serial);
|
al@20905
|
457 +
|
al@20905
|
458 + /* Use a uniquely seeded PRNG to get a prefix cookie for this agent,
|
al@20905
|
459 + * whose sequence will not correlate with the per-authentication session
|
al@20905
|
460 + * cookies.
|
al@20905
|
461 + */
|
al@20905
|
462 + append_rand_u128_str (cookie_prefix, agent_private_rand);
|
al@20905
|
463 + g_rand_free (agent_private_rand);
|
al@20905
|
464 +
|
al@20905
|
465 + agent->cookie_prefix = g_string_free (cookie_prefix, FALSE);
|
al@20905
|
466 +
|
al@20905
|
467 + /* And a newly seeded pool for per-session cookies */
|
al@20905
|
468 + agent->cookie_pool = g_rand_new ();
|
al@20905
|
469 + }
|
al@20905
|
470 +
|
al@20905
|
471 return agent;
|
al@20905
|
472 }
|
al@20905
|
473
|
al@20905
|
474 @@ -2193,7 +2257,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
|
al@20905
|
475 {
|
al@20905
|
476 PolkitBackendInteractiveAuthorityPrivate *priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
|
al@20905
|
477 AuthenticationSession *session;
|
al@20905
|
478 - gchar *cookie;
|
al@20905
|
479 GList *l;
|
al@20905
|
480 GList *identities;
|
al@20905
|
481 gchar *localized_message;
|
al@20905
|
482 @@ -2215,8 +2278,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
|
al@20905
|
483 &localized_icon_name,
|
al@20905
|
484 &localized_details);
|
al@20905
|
485
|
al@20905
|
486 - cookie = authentication_agent_new_cookie (agent);
|
al@20905
|
487 -
|
al@20905
|
488 identities = NULL;
|
al@20905
|
489
|
al@20905
|
490 /* select admin user if required by the implicit authorization */
|
al@20905
|
491 @@ -2279,7 +2340,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
|
al@20905
|
492 user_identities = g_list_prepend (NULL, polkit_unix_user_new (0));
|
al@20905
|
493
|
al@20905
|
494 session = authentication_session_new (agent,
|
al@20905
|
495 - cookie,
|
al@20905
|
496 subject,
|
al@20905
|
497 user_of_subject,
|
al@20905
|
498 caller,
|
al@20905
|
499 @@ -2335,7 +2395,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
|
al@20905
|
500 g_list_free_full (user_identities, g_object_unref);
|
al@20905
|
501 g_list_foreach (identities, (GFunc) g_object_unref, NULL);
|
al@20905
|
502 g_list_free (identities);
|
al@20905
|
503 - g_free (cookie);
|
al@20905
|
504
|
al@20905
|
505 g_free (localized_message);
|
al@20905
|
506 g_free (localized_icon_name);
|
al@20905
|
507 @@ -2482,7 +2541,9 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken
|
al@20905
|
508 goto out;
|
al@20905
|
509 }
|
al@20905
|
510
|
al@20905
|
511 - agent = authentication_agent_new (subject,
|
al@20905
|
512 + priv->agent_serial++;
|
al@20905
|
513 + agent = authentication_agent_new (priv->agent_serial,
|
al@20905
|
514 + subject,
|
al@20905
|
515 polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
|
al@20905
|
516 locale,
|
al@20905
|
517 object_path,
|
al@20905
|
518 --
|
al@20905
|
519 cgit v0.10.2
|
al@20905
|
520
|
al@20905
|
521 From 493aa5dc1d278ab9097110c1262f5229bbaf1766 Mon Sep 17 00:00:00 2001
|
al@20905
|
522 From: Colin Walters <walters@redhat.com>
|
al@20905
|
523 Date: Wed, 17 Jun 2015 13:07:02 -0400
|
al@20905
|
524 Subject: CVE-2015-4625: Bind use of cookies to specific uids
|
al@20905
|
525 MIME-Version: 1.0
|
al@20905
|
526 Content-Type: text/plain; charset=UTF-8
|
al@20905
|
527 Content-Transfer-Encoding: 8bit
|
al@20905
|
528
|
al@20905
|
529 http://lists.freedesktop.org/archives/polkit-devel/2015-June/000425.html
|
al@20905
|
530
|
al@20905
|
531 The "cookie" value that Polkit hands out is global to all polkit
|
al@20905
|
532 users. And when `AuthenticationAgentResponse` is invoked, we
|
al@20905
|
533 previously only received the cookie and *target* identity, and
|
al@20905
|
534 attempted to find an agent from that.
|
al@20905
|
535
|
al@20905
|
536 The problem is that the current cookie is just an integer
|
al@20905
|
537 counter, and if it overflowed, it would be possible for
|
al@20905
|
538 an successful authorization in one session to trigger a response
|
al@20905
|
539 in another session.
|
al@20905
|
540
|
al@20905
|
541 The overflow and ability to guess the cookie were fixed by the
|
al@20905
|
542 previous patch.
|
al@20905
|
543
|
al@20905
|
544 This patch is conceptually further hardening on top of that. Polkit
|
al@20905
|
545 currently treats uids as equivalent from a security domain
|
al@20905
|
546 perspective; there is no support for
|
al@20905
|
547 SELinux/AppArmor/etc. differentiation.
|
al@20905
|
548
|
al@20905
|
549 We can retrieve the uid from `getuid()` in the setuid helper, which
|
al@20905
|
550 allows us to ensure the uid invoking `AuthenticationAgentResponse2`
|
al@20905
|
551 matches that of the agent.
|
al@20905
|
552
|
al@20905
|
553 Then the authority only looks at authentication sessions matching the
|
al@20905
|
554 cookie that were created by a matching uid, thus removing the ability
|
al@20905
|
555 for different uids to interfere with each other entirely.
|
al@20905
|
556
|
al@20905
|
557 Several fixes to this patch were contributed by:
|
al@20905
|
558 Miloslav Trmač <mitr@redhat.com>
|
al@20905
|
559
|
al@20905
|
560 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=90837
|
al@20905
|
561 CVE: CVE-2015-4625
|
al@20905
|
562 Reported-by: Tavis Ormandy <taviso@google.com>
|
al@20905
|
563 Reviewed-by: Miloslav Trmač <mitr@redhat.com>
|
al@20905
|
564 Signed-off-by: Colin Walters <walters@redhat.com>
|
al@20905
|
565
|
al@20905
|
566 diff --git a/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml b/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml
|
al@20905
|
567 index 3b519c2..5beef7d 100644
|
al@20905
|
568 --- a/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml
|
al@20905
|
569 +++ b/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml
|
al@20905
|
570 @@ -8,7 +8,19 @@
|
al@20905
|
571 <annotation name="org.gtk.EggDBus.DocString" value="<para>This D-Bus interface is used for communication between the system-wide PolicyKit daemon and one or more authentication agents each running in a user session.</para><para>An authentication agent must implement this interface and register (passing the object path of the object implementing the interface) using the org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent() and org.freedesktop.PolicyKit1.Authority.UnregisterAuthenticationAgent() methods on the #org.freedesktop.PolicyKit1.Authority interface of the PolicyKit daemon.</para>"/>
|
al@20905
|
572
|
al@20905
|
573 <method name="BeginAuthentication">
|
al@20905
|
574 - <annotation name="org.gtk.EggDBus.DocString" value="<para>Called by the PolicyKit daemon when the authentication agent needs the user to authenticate as one of the identities in @identities for the action with the identifier @action_id.</para><para>Upon succesful authentication, the authentication agent must invoke the org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse() method on the #org.freedesktop.PolicyKit1.Authority interface of the PolicyKit daemon before returning.</para><para>If the user dismisses the authentication dialog, the authentication agent should return an error.</para>"/>
|
al@20905
|
575 + <annotation name="org.gtk.EggDBus.DocString" value="<para>Called
|
al@20905
|
576 + by the PolicyKit daemon when the authentication agent needs the
|
al@20905
|
577 + user to authenticate as one of the identities in @identities for
|
al@20905
|
578 + the action with the identifier @action_id.</para><para>This
|
al@20905
|
579 + authentication is normally achieved via the
|
al@20905
|
580 + polkit_agent_session_response() API, which invokes a private
|
al@20905
|
581 + setuid helper process to verify the authentication. When
|
al@20905
|
582 + successful, it calls the
|
al@20905
|
583 + org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse2()
|
al@20905
|
584 + method on the #org.freedesktop.PolicyKit1.Authority interface of
|
al@20905
|
585 + the PolicyKit daemon before returning. If the user dismisses the
|
al@20905
|
586 + authentication dialog, the authentication agent should call
|
al@20905
|
587 + polkit_agent_session_cancel().</para>"/>
|
al@20905
|
588
|
al@20905
|
589 <arg name="action_id" direction="in" type="s">
|
al@20905
|
590 <annotation name="org.gtk.EggDBus.DocString" value="The identifier for the action that the user is authentication for."/>
|
al@20905
|
591 diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml
|
al@20905
|
592 index fbfb9cd..f9021ee 100644
|
al@20905
|
593 --- a/data/org.freedesktop.PolicyKit1.Authority.xml
|
al@20905
|
594 +++ b/data/org.freedesktop.PolicyKit1.Authority.xml
|
al@20905
|
595 @@ -313,7 +313,29 @@
|
al@20905
|
596 </method>
|
al@20905
|
597
|
al@20905
|
598 <method name="AuthenticationAgentResponse">
|
al@20905
|
599 - <annotation name="org.gtk.EggDBus.DocString" value="Method for authentication agents to invoke on successful authentication. This method will fail unless a sufficiently privileged caller invokes it."/>
|
al@20905
|
600 + <annotation name="org.gtk.EggDBus.DocString" value="Method for authentication agents to invoke on successful
|
al@20905
|
601 +authentication, intended only for use by a privileged helper process
|
al@20905
|
602 +internal to polkit."/>
|
al@20905
|
603 +
|
al@20905
|
604 + <arg name="cookie" direction="in" type="s">
|
al@20905
|
605 + <annotation name="org.gtk.EggDBus.DocString" value="The cookie identifying the authentication request that was passed to the authentication agent."/>
|
al@20905
|
606 + </arg>
|
al@20905
|
607 +
|
al@20905
|
608 + <arg name="identity" direction="in" type="(sa{sv})">
|
al@20905
|
609 + <annotation name="org.gtk.EggDBus.Type" value="Identity"/>
|
al@20905
|
610 + <annotation name="org.gtk.EggDBus.DocString" value="A #Identity struct describing what identity was authenticated."/>
|
al@20905
|
611 + </arg>
|
al@20905
|
612 + </method>
|
al@20905
|
613 +
|
al@20905
|
614 + <method name="AuthenticationAgentResponse2">
|
al@20905
|
615 + <annotation name="org.gtk.EggDBus.DocString" value="Method for authentication agents to invoke on successful
|
al@20905
|
616 +authentication, intended only for use by a privileged helper process
|
al@20905
|
617 +internal to polkit. Note this method was added in 0.114, and should be preferred over AuthenticationAgentResponse
|
al@20905
|
618 +as it fixes a security issue."/>
|
al@20905
|
619 +
|
al@20905
|
620 + <arg name="uid" direction="in" type="u">
|
al@20905
|
621 + <annotation name="org.gtk.EggDBus.DocString" value="The real uid of the agent. Normally set by the setuid helper program."/>
|
al@20905
|
622 + </arg>
|
al@20905
|
623
|
al@20905
|
624 <arg name="cookie" direction="in" type="s">
|
al@20905
|
625 <annotation name="org.gtk.EggDBus.DocString" value="The cookie identifying the authentication request that was passed to the authentication agent."/>
|
al@20905
|
626 diff --git a/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml b/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
|
al@20905
|
627 index 6525e25..e66bf53 100644
|
al@20905
|
628 --- a/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
|
al@20905
|
629 +++ b/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
|
al@20905
|
630 @@ -42,6 +42,8 @@ Structure <link linkend="eggdbus-struct-TemporaryAuthorization">TemporaryAuth
|
al@20905
|
631 IN String object_path)
|
al@20905
|
632 <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse</link> (IN String cookie,
|
al@20905
|
633 IN <link linkend="eggdbus-struct-Identity">Identity</link> identity)
|
al@20905
|
634 +<link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse2</link> (IN uint32 uid, IN String cookie,
|
al@20905
|
635 + IN <link linkend="eggdbus-struct-Identity">Identity</link> identity)
|
al@20905
|
636 <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.EnumerateTemporaryAuthorizations">EnumerateTemporaryAuthorizations</link> (IN <link linkend="eggdbus-struct-Subject">Subject</link> subject,
|
al@20905
|
637 OUT Array<<link linkend="eggdbus-struct-TemporaryAuthorization">TemporaryAuthorization</link>> temporary_authorizations)
|
al@20905
|
638 <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RevokeTemporaryAuthorizations">RevokeTemporaryAuthorizations</link> (IN <link linkend="eggdbus-struct-Subject">Subject</link> subject)
|
al@20905
|
639 @@ -777,10 +779,52 @@ AuthenticationAgentResponse (IN String cookie,
|
al@20905
|
640 IN <link linkend="eggdbus-struct-Identity">Identity</link> identity)
|
al@20905
|
641 </programlisting>
|
al@20905
|
642 <para>
|
al@20905
|
643 -Method for authentication agents to invoke on successful authentication. This method will fail unless a sufficiently privileged caller invokes it.
|
al@20905
|
644 +Method for authentication agents to invoke on successful
|
al@20905
|
645 +authentication, intended only for use by a privileged helper process
|
al@20905
|
646 +internal to polkit. Deprecated in favor of AuthenticationAgentResponse2.
|
al@20905
|
647 + </para>
|
al@20905
|
648 +<variablelist role="params">
|
al@20905
|
649 + <varlistentry>
|
al@20905
|
650 + <term><literal>IN String <parameter>cookie</parameter></literal>:</term>
|
al@20905
|
651 + <listitem>
|
al@20905
|
652 + <para>
|
al@20905
|
653 +The cookie identifying the authentication request that was passed to the authentication agent.
|
al@20905
|
654 + </para>
|
al@20905
|
655 + </listitem>
|
al@20905
|
656 + </varlistentry>
|
al@20905
|
657 + <varlistentry>
|
al@20905
|
658 + <term><literal>IN <link linkend="eggdbus-struct-Identity">Identity</link> <parameter>identity</parameter></literal>:</term>
|
al@20905
|
659 + <listitem>
|
al@20905
|
660 + <para>
|
al@20905
|
661 +A <link linkend="eggdbus-struct-Identity">Identity</link> struct describing what identity was authenticated.
|
al@20905
|
662 + </para>
|
al@20905
|
663 + </listitem>
|
al@20905
|
664 + </varlistentry>
|
al@20905
|
665 +</variablelist>
|
al@20905
|
666 + </refsect2>
|
al@20905
|
667 + <refsect2 role="function" id="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse2">
|
al@20905
|
668 + <title>AuthenticationAgentResponse2 ()</title>
|
al@20905
|
669 + <programlisting>
|
al@20905
|
670 +AuthenticationAgentResponse2 (IN uint32 uid,
|
al@20905
|
671 + IN String cookie,
|
al@20905
|
672 + IN <link linkend="eggdbus-struct-Identity">Identity</link> identity)
|
al@20905
|
673 + </programlisting>
|
al@20905
|
674 + <para>
|
al@20905
|
675 +Method for authentication agents to invoke on successful
|
al@20905
|
676 +authentication, intended only for use by a privileged helper process
|
al@20905
|
677 +internal to polkit. Note this method was introduced in 0.114 to fix a security issue.
|
al@20905
|
678 </para>
|
al@20905
|
679 <variablelist role="params">
|
al@20905
|
680 <varlistentry>
|
al@20905
|
681 + <term><literal>IN uint32 <parameter>uid</parameter></literal>:</term>
|
al@20905
|
682 + <listitem>
|
al@20905
|
683 + <para>
|
al@20905
|
684 +The user id of the agent; normally this is the owner of the parent pid
|
al@20905
|
685 +of the process that invoked the internal setuid helper.
|
al@20905
|
686 + </para>
|
al@20905
|
687 + </listitem>
|
al@20905
|
688 + </varlistentry>
|
al@20905
|
689 + <varlistentry>
|
al@20905
|
690 <term><literal>IN String <parameter>cookie</parameter></literal>:</term>
|
al@20905
|
691 <listitem>
|
al@20905
|
692 <para>
|
al@20905
|
693 diff --git a/docs/polkit/overview.xml b/docs/polkit/overview.xml
|
al@20905
|
694 index 150a7bc..176d2ea 100644
|
al@20905
|
695 --- a/docs/polkit/overview.xml
|
al@20905
|
696 +++ b/docs/polkit/overview.xml
|
al@20905
|
697 @@ -314,16 +314,18 @@
|
al@20905
|
698 <para>
|
al@20905
|
699 Authentication agents are provided by desktop environments. When
|
al@20905
|
700 an user session starts, the agent registers with the polkit
|
al@20905
|
701 - Authority using
|
al@20905
|
702 - the <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent">RegisterAuthenticationAgent()</link>
|
al@20905
|
703 + Authority using the <link
|
al@20905
|
704 + linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent">RegisterAuthenticationAgent()</link>
|
al@20905
|
705 method. When services are needed, the authority will invoke
|
al@20905
|
706 - methods on
|
al@20905
|
707 - the <link linkend="eggdbus-interface-org.freedesktop.PolicyKit1.AuthenticationAgent">org.freedesktop.PolicyKit1.AuthenticationAgent</link>
|
al@20905
|
708 + methods on the <link
|
al@20905
|
709 + linkend="eggdbus-interface-org.freedesktop.PolicyKit1.AuthenticationAgent">org.freedesktop.PolicyKit1.AuthenticationAgent</link>
|
al@20905
|
710 D-Bus interface. Once the user is authenticated, (a privileged
|
al@20905
|
711 - part of) the agent invokes
|
al@20905
|
712 - the <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse()</link>
|
al@20905
|
713 - method. Note that the polkit Authority itself does not care
|
al@20905
|
714 - how the agent authenticates the user.
|
al@20905
|
715 + part of) the agent invokes the <link
|
al@20905
|
716 + linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse()</link>
|
al@20905
|
717 + method. This method should be treated as an internal
|
al@20905
|
718 + implementation detail, and callers should use the public shared
|
al@20905
|
719 + library API to invoke it, which currently uses a setuid helper
|
al@20905
|
720 + program.
|
al@20905
|
721 </para>
|
al@20905
|
722 <para>
|
al@20905
|
723 The <link linkend="ref-authentication-agent-api">libpolkit-agent-1</link>
|
al@20905
|
724 diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c
|
al@20905
|
725 index ab6d3cd..6bd684a 100644
|
al@20905
|
726 --- a/src/polkit/polkitauthority.c
|
al@20905
|
727 +++ b/src/polkit/polkitauthority.c
|
al@20905
|
728 @@ -1492,6 +1492,14 @@ polkit_authority_authentication_agent_response (PolkitAuthority *authority,
|
al@20905
|
729 gpointer user_data)
|
al@20905
|
730 {
|
al@20905
|
731 GVariant *identity_value;
|
al@20905
|
732 + /* Note that in reality, this API is only accessible to root, and
|
al@20905
|
733 + * only called from the setuid helper `polkit-agent-helper-1`.
|
al@20905
|
734 + *
|
al@20905
|
735 + * However, because this is currently public API, we avoid
|
al@20905
|
736 + * triggering warnings from ABI diff type programs by just grabbing
|
al@20905
|
737 + * the real uid of the caller here.
|
al@20905
|
738 + */
|
al@20905
|
739 + uid_t uid = getuid ();
|
al@20905
|
740
|
al@20905
|
741 g_return_if_fail (POLKIT_IS_AUTHORITY (authority));
|
al@20905
|
742 g_return_if_fail (cookie != NULL);
|
al@20905
|
743 @@ -1501,8 +1509,9 @@ polkit_authority_authentication_agent_response (PolkitAuthority *authority,
|
al@20905
|
744 identity_value = polkit_identity_to_gvariant (identity);
|
al@20905
|
745 g_variant_ref_sink (identity_value);
|
al@20905
|
746 g_dbus_proxy_call (authority->proxy,
|
al@20905
|
747 - "AuthenticationAgentResponse",
|
al@20905
|
748 - g_variant_new ("(s@(sa{sv}))",
|
al@20905
|
749 + "AuthenticationAgentResponse2",
|
al@20905
|
750 + g_variant_new ("(us@(sa{sv}))",
|
al@20905
|
751 + (guint32)uid,
|
al@20905
|
752 cookie,
|
al@20905
|
753 identity_value),
|
al@20905
|
754 G_DBUS_CALL_FLAGS_NONE,
|
al@20905
|
755 diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
|
al@20905
|
756 index 601a974..03a4e84 100644
|
al@20905
|
757 --- a/src/polkitbackend/polkitbackendauthority.c
|
al@20905
|
758 +++ b/src/polkitbackend/polkitbackendauthority.c
|
al@20905
|
759 @@ -355,6 +355,7 @@ polkit_backend_authority_unregister_authentication_agent (PolkitBackendAuthority
|
al@20905
|
760 gboolean
|
al@20905
|
761 polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority *authority,
|
al@20905
|
762 PolkitSubject *caller,
|
al@20905
|
763 + uid_t uid,
|
al@20905
|
764 const gchar *cookie,
|
al@20905
|
765 PolkitIdentity *identity,
|
al@20905
|
766 GError **error)
|
al@20905
|
767 @@ -373,7 +374,7 @@ polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority
|
al@20905
|
768 }
|
al@20905
|
769 else
|
al@20905
|
770 {
|
al@20905
|
771 - return klass->authentication_agent_response (authority, caller, cookie, identity, error);
|
al@20905
|
772 + return klass->authentication_agent_response (authority, caller, uid, cookie, identity, error);
|
al@20905
|
773 }
|
al@20905
|
774 }
|
al@20905
|
775
|
al@20905
|
776 @@ -587,6 +588,11 @@ static const gchar *server_introspection_data =
|
al@20905
|
777 " <arg type='s' name='cookie' direction='in'/>"
|
al@20905
|
778 " <arg type='(sa{sv})' name='identity' direction='in'/>"
|
al@20905
|
779 " </method>"
|
al@20905
|
780 + " <method name='AuthenticationAgentResponse2'>"
|
al@20905
|
781 + " <arg type='u' name='uid' direction='in'/>"
|
al@20905
|
782 + " <arg type='s' name='cookie' direction='in'/>"
|
al@20905
|
783 + " <arg type='(sa{sv})' name='identity' direction='in'/>"
|
al@20905
|
784 + " </method>"
|
al@20905
|
785 " <method name='EnumerateTemporaryAuthorizations'>"
|
al@20905
|
786 " <arg type='(sa{sv})' name='subject' direction='in'/>"
|
al@20905
|
787 " <arg type='a(ss(sa{sv})tt)' name='temporary_authorizations' direction='out'/>"
|
al@20905
|
788 @@ -1035,6 +1041,57 @@ server_handle_authentication_agent_response (Server *server,
|
al@20905
|
789 error = NULL;
|
al@20905
|
790 if (!polkit_backend_authority_authentication_agent_response (server->authority,
|
al@20905
|
791 caller,
|
al@20905
|
792 + (uid_t)-1,
|
al@20905
|
793 + cookie,
|
al@20905
|
794 + identity,
|
al@20905
|
795 + &error))
|
al@20905
|
796 + {
|
al@20905
|
797 + g_dbus_method_invocation_return_gerror (invocation, error);
|
al@20905
|
798 + g_error_free (error);
|
al@20905
|
799 + goto out;
|
al@20905
|
800 + }
|
al@20905
|
801 +
|
al@20905
|
802 + g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
al@20905
|
803 +
|
al@20905
|
804 + out:
|
al@20905
|
805 + if (identity != NULL)
|
al@20905
|
806 + g_object_unref (identity);
|
al@20905
|
807 +}
|
al@20905
|
808 +
|
al@20905
|
809 +static void
|
al@20905
|
810 +server_handle_authentication_agent_response2 (Server *server,
|
al@20905
|
811 + GVariant *parameters,
|
al@20905
|
812 + PolkitSubject *caller,
|
al@20905
|
813 + GDBusMethodInvocation *invocation)
|
al@20905
|
814 +{
|
al@20905
|
815 + const gchar *cookie;
|
al@20905
|
816 + GVariant *identity_gvariant;
|
al@20905
|
817 + PolkitIdentity *identity;
|
al@20905
|
818 + GError *error;
|
al@20905
|
819 + guint32 uid;
|
al@20905
|
820 +
|
al@20905
|
821 + identity = NULL;
|
al@20905
|
822 +
|
al@20905
|
823 + g_variant_get (parameters,
|
al@20905
|
824 + "(u&s@(sa{sv}))",
|
al@20905
|
825 + &uid,
|
al@20905
|
826 + &cookie,
|
al@20905
|
827 + &identity_gvariant);
|
al@20905
|
828 +
|
al@20905
|
829 + error = NULL;
|
al@20905
|
830 + identity = polkit_identity_new_for_gvariant (identity_gvariant, &error);
|
al@20905
|
831 + if (identity == NULL)
|
al@20905
|
832 + {
|
al@20905
|
833 + g_prefix_error (&error, "Error getting identity: ");
|
al@20905
|
834 + g_dbus_method_invocation_return_gerror (invocation, error);
|
al@20905
|
835 + g_error_free (error);
|
al@20905
|
836 + goto out;
|
al@20905
|
837 + }
|
al@20905
|
838 +
|
al@20905
|
839 + error = NULL;
|
al@20905
|
840 + if (!polkit_backend_authority_authentication_agent_response (server->authority,
|
al@20905
|
841 + caller,
|
al@20905
|
842 + (uid_t)uid,
|
al@20905
|
843 cookie,
|
al@20905
|
844 identity,
|
al@20905
|
845 &error))
|
al@20905
|
846 @@ -1222,6 +1279,8 @@ server_handle_method_call (GDBusConnection *connection,
|
al@20905
|
847 server_handle_unregister_authentication_agent (server, parameters, caller, invocation);
|
al@20905
|
848 else if (g_strcmp0 (method_name, "AuthenticationAgentResponse") == 0)
|
al@20905
|
849 server_handle_authentication_agent_response (server, parameters, caller, invocation);
|
al@20905
|
850 + else if (g_strcmp0 (method_name, "AuthenticationAgentResponse2") == 0)
|
al@20905
|
851 + server_handle_authentication_agent_response2 (server, parameters, caller, invocation);
|
al@20905
|
852 else if (g_strcmp0 (method_name, "EnumerateTemporaryAuthorizations") == 0)
|
al@20905
|
853 server_handle_enumerate_temporary_authorizations (server, parameters, caller, invocation);
|
al@20905
|
854 else if (g_strcmp0 (method_name, "RevokeTemporaryAuthorizations") == 0)
|
al@20905
|
855 diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h
|
al@20905
|
856 index f9f7385..88df82e 100644
|
al@20905
|
857 --- a/src/polkitbackend/polkitbackendauthority.h
|
al@20905
|
858 +++ b/src/polkitbackend/polkitbackendauthority.h
|
al@20905
|
859 @@ -147,6 +147,7 @@ struct _PolkitBackendAuthorityClass
|
al@20905
|
860
|
al@20905
|
861 gboolean (*authentication_agent_response) (PolkitBackendAuthority *authority,
|
al@20905
|
862 PolkitSubject *caller,
|
al@20905
|
863 + uid_t uid,
|
al@20905
|
864 const gchar *cookie,
|
al@20905
|
865 PolkitIdentity *identity,
|
al@20905
|
866 GError **error);
|
al@20905
|
867 @@ -249,6 +250,7 @@ gboolean polkit_backend_authority_unregister_authentication_agent (PolkitBackend
|
al@20905
|
868
|
al@20905
|
869 gboolean polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority *authority,
|
al@20905
|
870 PolkitSubject *caller,
|
al@20905
|
871 + uid_t uid,
|
al@20905
|
872 const gchar *cookie,
|
al@20905
|
873 PolkitIdentity *identity,
|
al@20905
|
874 GError **error);
|
al@20905
|
875 diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
|
al@20905
|
876 index 15adc6a..96725f7 100644
|
al@20905
|
877 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c
|
al@20905
|
878 +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
|
al@20905
|
879 @@ -108,8 +108,9 @@ static AuthenticationAgent *get_authentication_agent_for_subject (PolkitBackendI
|
al@20905
|
880 PolkitSubject *subject);
|
al@20905
|
881
|
al@20905
|
882
|
al@20905
|
883 -static AuthenticationSession *get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *authority,
|
al@20905
|
884 - const gchar *cookie);
|
al@20905
|
885 +static AuthenticationSession *get_authentication_session_for_uid_and_cookie (PolkitBackendInteractiveAuthority *authority,
|
al@20905
|
886 + uid_t uid,
|
al@20905
|
887 + const gchar *cookie);
|
al@20905
|
888
|
al@20905
|
889 static GList *get_authentication_sessions_initiated_by_system_bus_unique_name (PolkitBackendInteractiveAuthority *authority,
|
al@20905
|
890 const gchar *system_bus_unique_name);
|
al@20905
|
891 @@ -169,6 +170,7 @@ static gboolean polkit_backend_interactive_authority_unregister_authentication_a
|
al@20905
|
892
|
al@20905
|
893 static gboolean polkit_backend_interactive_authority_authentication_agent_response (PolkitBackendAuthority *authority,
|
al@20905
|
894 PolkitSubject *caller,
|
al@20905
|
895 + uid_t uid,
|
al@20905
|
896 const gchar *cookie,
|
al@20905
|
897 PolkitIdentity *identity,
|
al@20905
|
898 GError **error);
|
al@20905
|
899 @@ -440,6 +442,7 @@ struct AuthenticationAgent
|
al@20905
|
900 {
|
al@20905
|
901 volatile gint ref_count;
|
al@20905
|
902
|
al@20905
|
903 + uid_t creator_uid;
|
al@20905
|
904 PolkitSubject *scope;
|
al@20905
|
905 guint64 serial;
|
al@20905
|
906
|
al@20905
|
907 @@ -1603,6 +1606,7 @@ authentication_agent_unref (AuthenticationAgent *agent)
|
al@20905
|
908 static AuthenticationAgent *
|
al@20905
|
909 authentication_agent_new (guint64 serial,
|
al@20905
|
910 PolkitSubject *scope,
|
al@20905
|
911 + PolkitIdentity *creator,
|
al@20905
|
912 const gchar *unique_system_bus_name,
|
al@20905
|
913 const gchar *locale,
|
al@20905
|
914 const gchar *object_path,
|
al@20905
|
915 @@ -1611,6 +1615,10 @@ authentication_agent_new (guint64 serial,
|
al@20905
|
916 {
|
al@20905
|
917 AuthenticationAgent *agent;
|
al@20905
|
918 GDBusProxy *proxy;
|
al@20905
|
919 + PolkitUnixUser *creator_user;
|
al@20905
|
920 +
|
al@20905
|
921 + g_assert (POLKIT_IS_UNIX_USER (creator));
|
al@20905
|
922 + creator_user = POLKIT_UNIX_USER (creator);
|
al@20905
|
923
|
al@20905
|
924 if (!g_variant_is_object_path (object_path))
|
al@20905
|
925 {
|
al@20905
|
926 @@ -1638,6 +1646,7 @@ authentication_agent_new (guint64 serial,
|
al@20905
|
927 agent->ref_count = 1;
|
al@20905
|
928 agent->serial = serial;
|
al@20905
|
929 agent->scope = g_object_ref (scope);
|
al@20905
|
930 + agent->creator_uid = (uid_t)polkit_unix_user_get_uid (creator_user);
|
al@20905
|
931 agent->object_path = g_strdup (object_path);
|
al@20905
|
932 agent->unique_system_bus_name = g_strdup (unique_system_bus_name);
|
al@20905
|
933 agent->locale = g_strdup (locale);
|
al@20905
|
934 @@ -1736,8 +1745,9 @@ get_authentication_agent_for_subject (PolkitBackendInteractiveAuthority *authori
|
al@20905
|
935 }
|
al@20905
|
936
|
al@20905
|
937 static AuthenticationSession *
|
al@20905
|
938 -get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *authority,
|
al@20905
|
939 - const gchar *cookie)
|
al@20905
|
940 +get_authentication_session_for_uid_and_cookie (PolkitBackendInteractiveAuthority *authority,
|
al@20905
|
941 + uid_t uid,
|
al@20905
|
942 + const gchar *cookie)
|
al@20905
|
943 {
|
al@20905
|
944 PolkitBackendInteractiveAuthorityPrivate *priv;
|
al@20905
|
945 GHashTableIter hash_iter;
|
al@20905
|
946 @@ -1755,6 +1765,23 @@ get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *author
|
al@20905
|
947 {
|
al@20905
|
948 GList *l;
|
al@20905
|
949
|
al@20905
|
950 + /* We need to ensure that if somehow we have duplicate cookies
|
al@20905
|
951 + * due to wrapping, that the cookie used is matched to the user
|
al@20905
|
952 + * who called AuthenticationAgentResponse2. See
|
al@20905
|
953 + * http://lists.freedesktop.org/archives/polkit-devel/2015-June/000425.html
|
al@20905
|
954 + *
|
al@20905
|
955 + * Except if the legacy AuthenticationAgentResponse is invoked,
|
al@20905
|
956 + * we don't know the uid and hence use -1. Continue to support
|
al@20905
|
957 + * the old behavior for backwards compatibility, although everyone
|
al@20905
|
958 + * who is using our own setuid helper will automatically be updated
|
al@20905
|
959 + * to the new API.
|
al@20905
|
960 + */
|
al@20905
|
961 + if (uid != (uid_t)-1)
|
al@20905
|
962 + {
|
al@20905
|
963 + if (agent->creator_uid != uid)
|
al@20905
|
964 + continue;
|
al@20905
|
965 + }
|
al@20905
|
966 +
|
al@20905
|
967 for (l = agent->active_sessions; l != NULL; l = l->next)
|
al@20905
|
968 {
|
al@20905
|
969 AuthenticationSession *session = l->data;
|
al@20905
|
970 @@ -2544,6 +2571,7 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken
|
al@20905
|
971 priv->agent_serial++;
|
al@20905
|
972 agent = authentication_agent_new (priv->agent_serial,
|
al@20905
|
973 subject,
|
al@20905
|
974 + user_of_caller,
|
al@20905
|
975 polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
|
al@20905
|
976 locale,
|
al@20905
|
977 object_path,
|
al@20905
|
978 @@ -2757,6 +2785,7 @@ polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBack
|
al@20905
|
979 static gboolean
|
al@20905
|
980 polkit_backend_interactive_authority_authentication_agent_response (PolkitBackendAuthority *authority,
|
al@20905
|
981 PolkitSubject *caller,
|
al@20905
|
982 + uid_t uid,
|
al@20905
|
983 const gchar *cookie,
|
al@20905
|
984 PolkitIdentity *identity,
|
al@20905
|
985 GError **error)
|
al@20905
|
986 @@ -2799,7 +2828,7 @@ polkit_backend_interactive_authority_authentication_agent_response (PolkitBacken
|
al@20905
|
987 }
|
al@20905
|
988
|
al@20905
|
989 /* find the authentication session */
|
al@20905
|
990 - session = get_authentication_session_for_cookie (interactive_authority, cookie);
|
al@20905
|
991 + session = get_authentication_session_for_uid_and_cookie (interactive_authority, uid, cookie);
|
al@20905
|
992 if (session == NULL)
|
al@20905
|
993 {
|
al@20905
|
994 g_set_error (error,
|
al@20905
|
995 --
|
al@20905
|
996 cgit v0.10.2
|
al@20905
|
997
|
al@20905
|
998 --- ./configure.ac.orig
|
al@20905
|
999 +++ ./configure.ac
|
al@20905
|
1000 @@ -122,7 +122,7 @@
|
al@20905
|
1001 changequote([,])dnl
|
al@20905
|
1002 fi
|
al@20905
|
1003
|
al@20905
|
1004 -PKG_CHECK_MODULES(GLIB, [gio-2.0 >= 2.28.0])
|
al@20905
|
1005 +PKG_CHECK_MODULES(GLIB, [gmodule-2.0 gio-unix-2.0 gio-2.0 >= 2.30.0])
|
al@20905
|
1006 AC_SUBST(GLIB_CFLAGS)
|
al@20905
|
1007 AC_SUBST(GLIB_LIBS)
|
al@20905
|
1008
|