~ubuntu-branches/ubuntu/maverick/hal/maverick

« back to all changes in this revision

Viewing changes to hald/access-check.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2007-10-23 12:33:58 UTC
  • mto: (1.5.1 sid)
  • mto: This revision was merged to the branch mainline in revision 90.
  • Revision ID: james.westby@ubuntu.com-20071023123358-xaf8mjc5n84d5gtz
Tags: upstream-0.5.10
ImportĀ upstreamĀ versionĀ 0.5.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
#include <dbus/dbus.h>
39
39
#include <glib.h>
40
40
 
 
41
#ifdef HAVE_POLKIT
 
42
#include <polkit/polkit.h>
 
43
#endif
 
44
 
41
45
#include "hald.h"
 
46
#include "hald_dbus.h"
42
47
#include "logger.h"
43
48
#include "access-check.h"
44
49
 
106
111
        return ret;
107
112
}
108
113
 
 
114
#ifdef HAVE_POLKIT
 
115
static PolKitSeat *
 
116
get_pk_seat_from_ck_seat (CKSeat *seat)
 
117
{
 
118
        char *str;
 
119
        PolKitSeat *pk_seat;
 
120
        pk_seat = polkit_seat_new ();
 
121
        str = g_strdup_printf ("/org/freedesktop/ConsoleKit/%s", ck_seat_get_id (seat));
 
122
        polkit_seat_set_ck_objref (pk_seat, str);
 
123
        g_free (str);
 
124
        return pk_seat;
 
125
}
 
126
 
 
127
static PolKitSession *
 
128
get_pk_session_from_ck_session (CKSession *session)
 
129
{
 
130
        char *str;
 
131
        CKSeat *seat;
 
132
        PolKitSeat *pk_seat;
 
133
        PolKitSession *pk_session;
 
134
 
 
135
        seat = ck_session_get_seat (session);
 
136
        if (seat == NULL) {
 
137
                pk_seat = NULL;
 
138
        } else {
 
139
                pk_seat = get_pk_seat_from_ck_seat (seat);
 
140
        }
 
141
 
 
142
        pk_session = polkit_session_new ();
 
143
        if (pk_seat != NULL) {
 
144
                polkit_session_set_seat (pk_session, pk_seat);
 
145
                polkit_seat_unref (pk_seat);
 
146
        }
 
147
        str = g_strdup_printf ("/org/freedesktop/ConsoleKit/%s", ck_session_get_id (session));
 
148
        polkit_session_set_ck_objref (pk_session, str);
 
149
        g_free (str);
 
150
        polkit_session_set_uid (pk_session, ck_session_get_user (session));
 
151
        polkit_session_set_ck_is_active (pk_session, ck_session_is_active (session));
 
152
        polkit_session_set_ck_is_local (pk_session, ck_session_is_local (session));
 
153
        if (!ck_session_is_local (session)) {
 
154
                polkit_session_set_ck_remote_host (pk_session, ck_session_get_hostname (session));
 
155
        }
 
156
        return pk_session;
 
157
}
 
158
 
 
159
static PolKitCaller *
 
160
get_pk_caller_from_ci_tracker (CITracker *cit, const char *caller_unique_sysbus_name)
 
161
{
 
162
        CICallerInfo *ci;
 
163
        PolKitSession *pk_session;
 
164
        PolKitCaller *pk_caller;
 
165
        const char *ck_session_objpath;
 
166
        const char *selinux_context;
 
167
        
 
168
        pk_caller = NULL;
 
169
 
 
170
        ci = ci_tracker_get_info (cit, caller_unique_sysbus_name);
 
171
        if (ci == NULL) {
 
172
                HAL_ERROR (("Cannot get caller info for %s", caller_unique_sysbus_name));
 
173
                goto out;
 
174
        }
 
175
        
 
176
        ck_session_objpath = ci_tracker_caller_get_ck_session_path (ci);
 
177
        if (ck_session_objpath == NULL) {
 
178
                pk_session = NULL;
 
179
        } else {
 
180
                CKSession *session;
 
181
                
 
182
                session = ck_tracker_find_session (hald_dbus_get_ck_tracker (), ck_session_objpath);
 
183
                if (session == NULL) {
 
184
                        /* this should never happen */
 
185
                        HAL_ERROR (("ck_session_objpath is not NULL, but CKTracker don't know about the session!"));
 
186
                        goto out;
 
187
                }
 
188
                
 
189
                pk_session = get_pk_session_from_ck_session (session);
 
190
        }
 
191
 
 
192
        pk_caller = polkit_caller_new ();
 
193
        polkit_caller_set_dbus_name (pk_caller, caller_unique_sysbus_name);
 
194
        polkit_caller_set_uid (pk_caller, ci_tracker_caller_get_uid (ci));
 
195
        polkit_caller_set_pid (pk_caller, ci_tracker_caller_get_pid (ci));
 
196
        selinux_context = ci_tracker_caller_get_selinux_context (ci);
 
197
        if (selinux_context != NULL) {
 
198
                polkit_caller_set_selinux_context (pk_caller, selinux_context);
 
199
        }
 
200
        if (pk_session != NULL) {
 
201
                polkit_caller_set_ck_session (pk_caller, pk_session);
 
202
                polkit_session_unref (pk_session);
 
203
        }
 
204
 
 
205
out:
 
206
        return pk_caller;
 
207
}
 
208
#endif
 
209
 
109
210
/**
110
211
 * access_check_caller_have_access_to_device:
111
212
 * @cit: the CITracker object
112
 
 * @device: The device to check for
113
 
 * @privilege: the type of access; right now this can be #NULL or
114
 
 * "lock"; will be replaced by PolicyKit privileges in the future
 
213
 * @device: the device to check for
 
214
 * @action: the PolicyKit action to check for
115
215
 * @caller_unique_sysbus_name: The unique system bus connection
116
216
 * name (e.g. ":1.43") of the caller
 
217
 * @polkit_result_out: where to store the #PolicyKitResult return 
 
218
 * code. Will be ignored if HAL is not built with PolicyKit support
 
219
 * or if it's #NULL.
117
220
 *
118
221
 * Determine if a given caller should have access to a device. This
119
222
 * depends on how the security is set up and may change according to
145
248
 * Returns: TRUE iff the caller have access to the device.
146
249
 */
147
250
gboolean
148
 
access_check_caller_have_access_to_device (CITracker *cit, HalDevice *device, const char *privilege, const char *caller_unique_sysbus_name)
 
251
access_check_caller_have_access_to_device (CITracker   *cit, 
 
252
                                           HalDevice   *device, 
 
253
                                           const char  *action, 
 
254
                                           const char  *caller_unique_sysbus_name,
 
255
                                           int         *polkit_result_out)
149
256
#ifdef HAVE_CONKIT
150
257
{
151
258
        gboolean ret;
152
259
        CICallerInfo *ci;
 
260
#ifdef HAVE_POLKIT
 
261
        PolKitCaller *pk_caller = NULL;
 
262
        PolKitAction *pk_action = NULL;
 
263
        PolKitResult pk_result;
 
264
#endif
153
265
 
154
266
        ret = FALSE;
155
267
 
159
271
                goto out;
160
272
        }
161
273
 
 
274
        /* HAL user and uid 0 are always allowed
 
275
         * (TODO: is this sane? probably needs to go through PolicyKit too..) 
 
276
         */
162
277
        if (ci_tracker_caller_get_uid (ci) == 0 ||
163
278
            ci_tracker_caller_get_uid (ci) == geteuid ()) {
164
279
                ret = TRUE;
165
 
                goto out;
166
 
        }
167
 
 
 
280
#ifdef HAVE_POLKIT
 
281
                if (polkit_result_out != NULL)
 
282
                        *polkit_result_out = POLKIT_RESULT_YES;
 
283
#endif
 
284
                goto out;
 
285
        }
 
286
 
 
287
        /* allow inactive sessions to lock interfaces on root computer device object 
 
288
         * (TODO FIXME: restrict to local sessions?)
 
289
         */
 
290
        if (action != NULL && 
 
291
            strcmp (action, "hal-lock") == 0 &&
 
292
            strcmp (hal_device_get_udi (device), "/org/freedesktop/Hal/devices/computer") == 0) {
 
293
                ret = TRUE;
 
294
#ifdef HAVE_POLKIT
 
295
                if (polkit_result_out != NULL)
 
296
                        *polkit_result_out = POLKIT_RESULT_YES;
 
297
#endif
 
298
                goto out;
 
299
        }
 
300
 
 
301
#ifdef HAVE_POLKIT
 
302
        pk_action = polkit_action_new ();
 
303
        polkit_action_set_action_id (pk_action, action);
 
304
        
 
305
        pk_caller = get_pk_caller_from_ci_tracker (cit, caller_unique_sysbus_name);
 
306
        if (pk_caller == NULL)
 
307
                goto out;
 
308
 
 
309
        pk_result = polkit_context_can_caller_do_action (pk_context,
 
310
                                                         pk_action,
 
311
                                                         pk_caller);
 
312
 
 
313
        if (polkit_result_out != NULL)
 
314
                *polkit_result_out = pk_result;
 
315
 
 
316
        if (pk_result != POLKIT_RESULT_YES)
 
317
                goto out;
 
318
#else
168
319
        /* must be tracked by ConsoleKit */
169
320
        if (ci_tracker_caller_get_ck_session_path (ci) == NULL) {
170
321
                goto out;
171
322
        }
172
 
 
 
323
        
173
324
        /* require caller to be local */
174
325
        if (!ci_tracker_caller_is_local (ci))
175
326
                goto out;
176
 
 
177
 
        /* allow inactive sessions to lock interfaces on root computer device object */
178
 
        if (privilege != NULL && 
179
 
            strcmp (privilege, "lock") == 0 && 
180
 
            strcmp (hal_device_get_udi (device), "/org/freedesktop/Hal/devices/computer") == 0) {
181
 
                ret = TRUE;
182
 
                goto out;
183
 
        }
184
327
        
185
328
        /* require caller to be in active session */
186
329
        if (!ci_tracker_caller_in_active_session (ci))
187
 
                goto out;
 
330
                        goto out;
 
331
#endif
188
332
                
189
333
        ret = TRUE;
190
334
out:
 
335
#ifdef HAVE_POLKIT
 
336
        if (pk_caller != NULL)
 
337
                polkit_caller_unref (pk_caller);
 
338
        if (pk_action != NULL)
 
339
                polkit_action_unref (pk_action);
 
340
#endif
191
341
        return ret;
192
342
}
193
343
#else /* HAVE_CONKIT */
278
428
                for (n = 0; global_holders[n] != NULL; n++) {
279
429
                        if (strcmp (global_holders[n], caller_unique_sysbus_name) == 0) {
280
430
                                /* we are holding the global lock... */
281
 
                                if (access_check_caller_have_access_to_device (cit, device, NULL, global_holders[n])) {
 
431
                                if (access_check_caller_have_access_to_device (
 
432
                                            cit, device, "hal-lock", global_holders[n], NULL)) {
282
433
                                        /* only applies if the caller can access the device... */
283
434
                                        is_locked_by_self = TRUE;
284
435
                                        /* this is good enough; we are holding the lock ourselves */
289
440
                                /* Someone else is holding the global lock.. check if that someone
290
441
                                 * actually have access to the device...
291
442
                                 */
292
 
                                if (access_check_caller_have_access_to_device (cit, device, NULL, global_holders[n])) {
 
443
                                if (access_check_caller_have_access_to_device (
 
444
                                            cit, device, "hal-lock", global_holders[n], NULL)) {
293
445
                                        /* They certainly do. Mark as locked. */
294
446
                                        is_locked = TRUE;
295
447
                                }
375
527
                        if (caller_unique_sysbus_name == NULL || /* <-- callers using direct connection to hald */
376
528
                            strcmp (global_holders[n], caller_unique_sysbus_name) != 0) {
377
529
                                /* someone else is holding the global lock... */
378
 
                                if (access_check_caller_have_access_to_device (cit, device, NULL, global_holders[n])) {
 
530
                                if (access_check_caller_have_access_to_device (
 
531
                                            cit, device, "hal-lock", global_holders[n], NULL)) {
379
532
                                        /* ... and they can can access the device */
380
533
                                        goto out;
381
534
                                }