Gentoo Archives: gentoo-commits

From: Alexandre Restovtsev <tetromino@×××××.com>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/openrc-settingsd:master commit in: src/
Date: Mon, 06 Feb 2012 10:25:07
Message-Id: 52f4dc6163ecbc334f9ba949d6436f650ecf138d.tetromino@gentoo
1 commit: 52f4dc6163ecbc334f9ba949d6436f650ecf138d
2 Author: Alexandre Rostovtsev <tetromino <AT> gentoo <DOT> org>
3 AuthorDate: Mon Feb 6 10:19:08 2012 +0000
4 Commit: Alexandre Restovtsev <tetromino <AT> gmail <DOT> com>
5 CommitDate: Mon Feb 6 10:19:08 2012 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/openrc-settingsd.git;a=commit;h=52f4dc61
7
8 Check polkit authorization asynchronously
9
10 The other alternative (spawning a thread for each authorization
11 request) seems less elegant, since such requests can take arbitrarily
12 long to complete.
13
14 ---
15 src/bus-utils.c | 137 +++++++++++++++++++++-------
16 src/bus-utils.h | 13 ++-
17 src/hostnamed.c | 275 ++++++++++++++++++++++++++++++++++++++-----------------
18 3 files changed, 302 insertions(+), 123 deletions(-)
19
20 diff --git a/src/bus-utils.c b/src/bus-utils.c
21 index d3bc7b2..aef8037 100644
22 --- a/src/bus-utils.c
23 +++ b/src/bus-utils.c
24 @@ -20,44 +20,115 @@
25 #include <gio/gio.h>
26 #include <polkit/polkit.h>
27
28 +#include "bus-utils.h"
29 +
30 +struct check_polkit_data {
31 + const gchar *unique_name;
32 + const gchar *action_id;
33 + gboolean user_interaction;
34 + GAsyncReadyCallback callback;
35 + gpointer user_data;
36 +
37 + PolkitAuthority *authority;
38 + PolkitSubject *subject;
39 +};
40 +
41 +void
42 +check_polkit_data_free (struct check_polkit_data *data)
43 +{
44 + if (data == NULL)
45 + return;
46 +
47 + if (data->subject != NULL)
48 + g_object_unref (data->subject);
49 + if (data->authority != NULL)
50 + g_object_unref (data->authority);
51 +
52 + g_free (data);
53 +}
54 +
55 gboolean
56 -check_polkit (const gchar *unique_name,
57 - const gchar *action_id,
58 - const gboolean user_interaction,
59 - GError **error)
60 +check_polkit_finish (GAsyncResult *res,
61 + GError **error)
62 {
63 - gboolean ret = FALSE;
64 - GDBusConnection *connection = NULL;
65 - PolkitAuthority *authority = NULL;
66 - PolkitSubject *subject = NULL;
67 - PolkitAuthorizationResult *result = NULL;
68 -
69 - if ((authority = polkit_authority_get_sync (NULL, error)) == NULL)
70 - goto end;
71 -
72 - if (unique_name == NULL || action_id == NULL ||
73 - (subject = polkit_system_bus_name_new (unique_name)) == NULL) {
74 - g_propagate_error (error,
75 - g_error_new (POLKIT_ERROR, POLKIT_ERROR_FAILED,
76 - "Authorizing for '%s': failed sanity check", action_id));
77 - goto end;
78 - }
79 + GSimpleAsyncResult *simple;
80 +
81 + simple = G_SIMPLE_ASYNC_RESULT (res);
82 + if (g_simple_async_result_propagate_error (simple, error))
83 + return FALSE;
84 +
85 + return g_simple_async_result_get_op_res_gboolean (simple);
86 +}
87 +
88 +static void
89 +check_polkit_authorization_cb (GObject *source_object,
90 + GAsyncResult *res,
91 + gpointer _data)
92 +{
93 + struct check_polkit_data *data;
94 + PolkitAuthorizationResult *result;
95 + GSimpleAsyncResult *simple;
96 + GError *err = NULL;
97
98 - if ((result = polkit_authority_check_authorization_sync (authority, subject, action_id, NULL, (PolkitCheckAuthorizationFlags) user_interaction, NULL, error)) == NULL)
99 - goto end;
100 + data = (struct check_polkit_data *) _data;
101 + if ((result = polkit_authority_check_authorization_finish (data->authority, res, &err)) == NULL) {
102 + g_simple_async_report_take_gerror_in_idle (NULL, data->callback, data->user_data, err);
103 + goto out;
104 + }
105
106 - if ((ret = polkit_authorization_result_get_is_authorized (result)) == FALSE) {
107 - g_propagate_error (error,
108 - g_error_new (POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED,
109 - "Authorizing for '%s': not authorized", action_id));
110 + if (!polkit_authorization_result_get_is_authorized (result)) {
111 + g_simple_async_report_error_in_idle (NULL, data->callback, data->user_data, POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED, "Authorizing for '%s': not authorized", data->action_id);
112 + goto out;
113 }
114 -
115 - end:
116 + simple = g_simple_async_result_new (NULL, data->callback, data->user_data, check_polkit_async);
117 + g_simple_async_result_set_op_res_gboolean (simple, TRUE);
118 + g_simple_async_result_complete_in_idle (simple);
119 + g_object_unref (simple);
120 +
121 + out:
122 + check_polkit_data_free (data);
123 if (result != NULL)
124 g_object_unref (result);
125 - if (subject != NULL)
126 - g_object_unref (subject);
127 - if (authority != NULL)
128 - g_object_unref (authority);
129 - return ret;
130 +}
131 +
132 +static void
133 +check_polkit_authority_cb (GObject *source_object,
134 + GAsyncResult *res,
135 + gpointer _data)
136 +{
137 + struct check_polkit_data *data;
138 + GError *err = NULL;
139 +
140 + data = (struct check_polkit_data *) _data;
141 + if ((data->authority = polkit_authority_get_finish (res, &err)) == NULL) {
142 + g_simple_async_report_take_gerror_in_idle (NULL, data->callback, data->user_data, err);
143 + check_polkit_data_free (data);
144 + return;
145 + }
146 + if (data->unique_name == NULL || data->action_id == NULL ||
147 + (data->subject = polkit_system_bus_name_new (data->unique_name)) == NULL) {
148 + g_simple_async_report_error_in_idle (NULL, data->callback, data->user_data, POLKIT_ERROR, POLKIT_ERROR_FAILED, "Authorizing for '%s': failed sanity check", data->action_id);
149 + check_polkit_data_free (data);
150 + return;
151 + }
152 + polkit_authority_check_authorization (data->authority, data->subject, data->action_id, NULL, (PolkitCheckAuthorizationFlags) data->user_interaction, NULL, check_polkit_authorization_cb, data);
153 +}
154 +
155 +void
156 +check_polkit_async (const gchar *unique_name,
157 + const gchar *action_id,
158 + const gboolean user_interaction,
159 + GAsyncReadyCallback callback,
160 + gpointer user_data)
161 +{
162 + struct check_polkit_data *data;
163 +
164 + data = g_new0 (struct check_polkit_data, 1);
165 + data->unique_name = unique_name;
166 + data->action_id = action_id;
167 + data->user_interaction = user_interaction;
168 + data->callback = callback;
169 + data->user_data = user_data;
170 +
171 + polkit_authority_get_async (NULL, check_polkit_authority_cb, data);
172 }
173 \ No newline at end of file
174
175 diff --git a/src/bus-utils.h b/src/bus-utils.h
176 index 31a2ef1..f2e80ea 100644
177 --- a/src/bus-utils.h
178 +++ b/src/bus-utils.h
179 @@ -21,10 +21,15 @@
180
181 #include <glib.h>
182
183 +void
184 +check_polkit_async (const gchar *unique_name,
185 + const gchar *action_id,
186 + const gboolean user_interaction,
187 + GAsyncReadyCallback callback,
188 + gpointer user_data);
189 +
190 gboolean
191 -check_polkit (const gchar *unique_name,
192 - const gchar *action_id,
193 - const gboolean user_interaction,
194 - GError **error);
195 +check_polkit_finish (GAsyncResult *res,
196 + GError **error);
197
198 #endif
199 \ No newline at end of file
200
201 diff --git a/src/hostnamed.c b/src/hostnamed.c
202 index 4f95d04..c5914bd 100644
203 --- a/src/hostnamed.c
204 +++ b/src/hostnamed.c
205 @@ -36,6 +36,11 @@
206 #define QUOTE(macro) #macro
207 #define STR(macro) QUOTE(macro)
208
209 +struct invoked_name {
210 + GDBusMethodInvocation *invocation;
211 + gchar *name; /* newly allocated */
212 +};
213 +
214 guint bus_id = 0;
215 gboolean read_only = FALSE;
216
217 @@ -103,152 +108,250 @@ guess_icon_name ()
218 icon_name = g_strdup ("computer");
219 }
220
221 -static gboolean
222 -on_handle_set_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
223 - GDBusMethodInvocation *invocation,
224 - const gchar *name,
225 - const gboolean user_interaction,
226 - gpointer user_data)
227 +static void
228 +on_handle_set_hostname_authorized_cb (GObject *source_object,
229 + GAsyncResult *res,
230 + gpointer user_data)
231 {
232 GError *err = NULL;
233 -
234 - if (read_only) {
235 - g_dbus_method_invocation_return_dbus_error (invocation,
236 - DBUS_ERROR_NOT_SUPPORTED,
237 - "openrc-settingsd hostnamed is in read-only mode");
238 - goto end;
239 - }
240 -
241 - if (!check_polkit (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-hostname", user_interaction, &err)) {
242 - g_dbus_method_invocation_return_gerror (invocation, err);
243 - goto end;
244 + struct invoked_name *data;
245 +
246 + data = (struct invoked_name *) user_data;
247 + if (!check_polkit_finish (res, &err)) {
248 + g_dbus_method_invocation_return_gerror (data->invocation, err);
249 + goto out;
250 }
251
252 G_LOCK (hostname);
253 /* Don't allow an empty or invalid hostname */
254 - if (!hostname_is_valid (name)) {
255 - name = hostname;
256 - if (!hostname_is_valid (name))
257 - name = "localhost";
258 + if (!hostname_is_valid (data->name)) {
259 + if (data->name != NULL)
260 + g_free (data->name);
261 +
262 + if (hostname_is_valid (hostname))
263 + data->name = g_strdup (hostname);
264 + else
265 + data->name = g_strdup ("localhost");
266 }
267 - if (sethostname (name, strlen(name))) {
268 + if (sethostname (data->name, strlen(data->name))) {
269 int errsv = errno;
270 - g_dbus_method_invocation_return_dbus_error (invocation,
271 + g_dbus_method_invocation_return_dbus_error (data->invocation,
272 DBUS_ERROR_FAILED,
273 strerror (errsv));
274 G_UNLOCK (hostname);
275 - goto end;
276 + goto out;
277 }
278 - g_strlcpy (hostname, name, HOST_NAME_MAX + 1);
279 - openrc_settingsd_hostnamed_hostname1_complete_set_hostname (hostname1, invocation);
280 + g_strlcpy (hostname, data->name, HOST_NAME_MAX + 1);
281 + openrc_settingsd_hostnamed_hostname1_complete_set_hostname (hostname1, data->invocation);
282 openrc_settingsd_hostnamed_hostname1_set_hostname (hostname1, hostname);
283 G_UNLOCK (hostname);
284
285 - end:
286 - return TRUE;
287 + out:
288 + g_free (data->name);
289 + g_free (data);
290 + if (err != NULL)
291 + g_error_free (err);
292 }
293
294 static gboolean
295 -on_handle_set_static_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
296 - GDBusMethodInvocation *invocation,
297 - const gchar *name,
298 - const gboolean user_interaction,
299 - gpointer user_data)
300 +on_handle_set_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
301 + GDBusMethodInvocation *invocation,
302 + const gchar *name,
303 + const gboolean user_interaction,
304 + gpointer user_data)
305 {
306 - ShellUtilsTrivial *confd_file = NULL;
307 - GError *err = NULL;
308 -
309 - if (read_only) {
310 + if (read_only)
311 g_dbus_method_invocation_return_dbus_error (invocation,
312 DBUS_ERROR_NOT_SUPPORTED,
313 "openrc-settingsd hostnamed is in read-only mode");
314 - goto end;
315 + else {
316 + struct invoked_name *data;
317 + data = g_new0 (struct invoked_name, 1);
318 + data->invocation = invocation;
319 + data->name = g_strdup (name);
320 + check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-hostname", user_interaction, on_handle_set_hostname_authorized_cb, data);
321 }
322
323 - if (!check_polkit (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-static-hostname", user_interaction, &err)) {
324 - g_dbus_method_invocation_return_gerror (invocation, err);
325 - goto end;
326 + return TRUE;
327 +}
328 +
329 +static void
330 +on_handle_set_static_hostname_authorized_cb (GObject *source_object,
331 + GAsyncResult *res,
332 + gpointer user_data)
333 +{
334 + GError *err = NULL;
335 + struct invoked_name *data;
336 +
337 + data = (struct invoked_name *) user_data;
338 + if (!check_polkit_finish (res, &err)) {
339 + g_dbus_method_invocation_return_gerror (data->invocation, err);
340 + goto out;
341 }
342
343 G_LOCK (static_hostname);
344 /* Don't allow an empty or invalid hostname */
345 - if (!hostname_is_valid (name))
346 - name = "localhost";
347 + if (!hostname_is_valid (data->name)) {
348 + if (data->name != NULL)
349 + g_free (data->name);
350 +
351 + data->name = g_strdup ("localhost");
352 + }
353
354 - if (!shell_utils_trivial_set_and_save (static_hostname_file, &err, "hostname", "HOSTNAME", name, NULL)) {
355 - g_dbus_method_invocation_return_gerror (invocation, err);
356 + if (!shell_utils_trivial_set_and_save (static_hostname_file, &err, "hostname", "HOSTNAME", data->name, NULL)) {
357 + g_dbus_method_invocation_return_gerror (data->invocation, err);
358 G_UNLOCK (static_hostname);
359 - goto end;
360 + goto out;
361 }
362
363 g_free (static_hostname);
364 - static_hostname = g_strdup (name);
365 - openrc_settingsd_hostnamed_hostname1_complete_set_static_hostname (hostname1, invocation);
366 + static_hostname = data->name; /* data->name is g_strdup-ed already */;
367 + openrc_settingsd_hostnamed_hostname1_complete_set_static_hostname (hostname1, data->invocation);
368 openrc_settingsd_hostnamed_hostname1_set_static_hostname (hostname1, static_hostname);
369 G_UNLOCK (static_hostname);
370
371 - end:
372 - shell_utils_trivial_free (confd_file);
373 + out:
374 + g_free (data);
375 if (err != NULL)
376 g_error_free (err);
377 +}
378 +
379 +static gboolean
380 +on_handle_set_static_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
381 + GDBusMethodInvocation *invocation,
382 + const gchar *name,
383 + const gboolean user_interaction,
384 + gpointer user_data)
385 +{
386 + if (read_only)
387 + g_dbus_method_invocation_return_dbus_error (invocation,
388 + DBUS_ERROR_NOT_SUPPORTED,
389 + "openrc-settingsd hostnamed is in read-only mode");
390 + else {
391 + struct invoked_name *data;
392 + data = g_new0 (struct invoked_name, 1);
393 + data->invocation = invocation;
394 + data->name = g_strdup (name);
395 + check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-static-hostname", user_interaction, on_handle_set_static_hostname_authorized_cb, data);
396 + }
397
398 return TRUE; /* Always return TRUE to indicate signal has been handled */
399 }
400
401 -static gboolean
402 -on_handle_set_machine_info (OpenrcSettingsdHostnamedHostname1 *hostname1,
403 - GDBusMethodInvocation *invocation,
404 - const gchar *name,
405 - const gboolean user_interaction,
406 - gpointer user_data)
407 +static void
408 +on_handle_set_pretty_hostname_authorized_cb (GObject *source_object,
409 + GAsyncResult *res,
410 + gpointer user_data)
411 {
412 - ShellUtilsTrivial *confd_file = NULL;
413 GError *err = NULL;
414 - gboolean is_pretty_hostname = GPOINTER_TO_INT(user_data);
415 + struct invoked_name *data;
416 +
417 + data = (struct invoked_name *) user_data;
418 + if (!check_polkit_finish (res, &err)) {
419 + g_dbus_method_invocation_return_gerror (data->invocation, err);
420 + goto out;
421 + }
422 +
423 + G_LOCK (machine_info);
424 + /* Don't allow a null pretty hostname */
425 + if (data->name == NULL)
426 + data->name = g_strdup ("");
427
428 - if (read_only) {
429 + if (!shell_utils_trivial_set_and_save (machine_info_file, &err, "PRETTY_HOSTNAME", NULL, data->name, NULL)) {
430 + g_dbus_method_invocation_return_gerror (data->invocation, err);
431 + G_UNLOCK (machine_info);
432 + goto out;
433 + }
434 +
435 + g_free (pretty_hostname);
436 + pretty_hostname = data->name; /* data->name is g_strdup-ed already */
437 + openrc_settingsd_hostnamed_hostname1_complete_set_pretty_hostname (hostname1, data->invocation);
438 + openrc_settingsd_hostnamed_hostname1_set_pretty_hostname (hostname1, pretty_hostname);
439 + G_UNLOCK (machine_info);
440 +
441 + out:
442 + g_free (data);
443 + if (err != NULL)
444 + g_error_free (err);
445 +}
446 +
447 +static gboolean
448 +on_handle_set_pretty_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1,
449 + GDBusMethodInvocation *invocation,
450 + const gchar *name,
451 + const gboolean user_interaction,
452 + gpointer user_data)
453 +{
454 + if (read_only)
455 g_dbus_method_invocation_return_dbus_error (invocation,
456 DBUS_ERROR_NOT_SUPPORTED,
457 "openrc-settingsd hostnamed is in read-only mode");
458 - goto end;
459 + else {
460 + struct invoked_name *data;
461 + data = g_new0 (struct invoked_name, 1);
462 + data->invocation = invocation;
463 + data->name = g_strdup (name);
464 + check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-machine-info", user_interaction, on_handle_set_pretty_hostname_authorized_cb, data);
465 }
466
467 - if (!check_polkit (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-machine-info", user_interaction, &err)) {
468 - g_dbus_method_invocation_return_gerror (invocation, err);
469 - goto end;
470 + return TRUE; /* Always return TRUE to indicate signal has been handled */
471 +}
472 +
473 +static void
474 +on_handle_set_icon_name_authorized_cb (GObject *source_object,
475 + GAsyncResult *res,
476 + gpointer user_data)
477 +{
478 + GError *err = NULL;
479 + struct invoked_name *data;
480 +
481 + data = (struct invoked_name *) user_data;
482 + if (!check_polkit_finish (res, &err)) {
483 + g_dbus_method_invocation_return_gerror (data->invocation, err);
484 + goto out;
485 }
486
487 G_LOCK (machine_info);
488 /* Don't allow a null pretty hostname */
489 - if (name == NULL)
490 - name = "";
491 + if (data->name == NULL)
492 + data->name = g_strdup ("");
493
494 - if ((is_pretty_hostname &&
495 - !shell_utils_trivial_set_and_save (machine_info_file, &err, "PRETTY_HOSTNAME", NULL, name, NULL)) ||
496 - (!is_pretty_hostname &&
497 - !shell_utils_trivial_set_and_save (machine_info_file, &err, "ICON_NAME", NULL, name, NULL))) {
498 - g_dbus_method_invocation_return_gerror (invocation, err);
499 + if (!shell_utils_trivial_set_and_save (machine_info_file, &err, "ICON_NAME", NULL, data->name, NULL)) {
500 + g_dbus_method_invocation_return_gerror (data->invocation, err);
501 G_UNLOCK (machine_info);
502 - goto end;
503 + goto out;
504 }
505
506 - if (is_pretty_hostname) {
507 - g_free (pretty_hostname);
508 - pretty_hostname = g_strdup (name);
509 - openrc_settingsd_hostnamed_hostname1_complete_set_pretty_hostname (hostname1, invocation);
510 - openrc_settingsd_hostnamed_hostname1_set_pretty_hostname (hostname1, pretty_hostname);
511 - } else {
512 - g_free (icon_name);
513 - icon_name = g_strdup (name);
514 - openrc_settingsd_hostnamed_hostname1_complete_set_icon_name (hostname1, invocation);
515 - openrc_settingsd_hostnamed_hostname1_set_icon_name (hostname1, icon_name);
516 - }
517 + g_free (icon_name);
518 + icon_name = data->name; /* data->name is g_strdup-ed already */
519 + openrc_settingsd_hostnamed_hostname1_complete_set_icon_name (hostname1, data->invocation);
520 + openrc_settingsd_hostnamed_hostname1_set_icon_name (hostname1, icon_name);
521 G_UNLOCK (machine_info);
522
523 - end:
524 - shell_utils_trivial_free (confd_file);
525 + out:
526 + g_free (data);
527 if (err != NULL)
528 g_error_free (err);
529 +}
530 +
531 +static gboolean
532 +on_handle_set_icon_name (OpenrcSettingsdHostnamedHostname1 *hostname1,
533 + GDBusMethodInvocation *invocation,
534 + const gchar *name,
535 + const gboolean user_interaction,
536 + gpointer user_data)
537 +{
538 + if (read_only)
539 + g_dbus_method_invocation_return_dbus_error (invocation,
540 + DBUS_ERROR_NOT_SUPPORTED,
541 + "openrc-settingsd hostnamed is in read-only mode");
542 + else {
543 + struct invoked_name *data;
544 + data = g_new0 (struct invoked_name, 1);
545 + data->invocation = invocation;
546 + data->name = g_strdup (name);
547 + check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.hostname1.set-machine-info", user_interaction, on_handle_set_icon_name_authorized_cb, data);
548 + }
549
550 return TRUE; /* Always return TRUE to indicate signal has been handled */
551 }
552 @@ -272,8 +375,8 @@ on_bus_acquired (GDBusConnection *connection,
553
554 g_signal_connect (hostname1, "handle-set-hostname", G_CALLBACK (on_handle_set_hostname), NULL);
555 g_signal_connect (hostname1, "handle-set-static-hostname", G_CALLBACK (on_handle_set_static_hostname), NULL);
556 - g_signal_connect (hostname1, "handle-set-pretty-hostname", G_CALLBACK (on_handle_set_machine_info), GINT_TO_POINTER(TRUE));
557 - g_signal_connect (hostname1, "handle-set-icon-name", G_CALLBACK (on_handle_set_machine_info), GINT_TO_POINTER(FALSE));
558 + g_signal_connect (hostname1, "handle-set-pretty-hostname", G_CALLBACK (on_handle_set_pretty_hostname), NULL);
559 + g_signal_connect (hostname1, "handle-set-icon-name", G_CALLBACK (on_handle_set_icon_name), NULL);
560
561 if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (hostname1),
562 connection,