~ubuntu-branches/ubuntu/oneiric/pulseaudio/oneiric

« back to all changes in this revision

Viewing changes to src/daemon/polkit.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2007-12-04 00:56:08 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20071204005608-y1xqvcu45g1yxtlu
Tags: 0.9.8-1ubuntu1
"Hail our new PulseAudio overlords (part two)."

* Merge from Debian unstable.
* Ubuntu-specific changes:
  - debian/control:
    + Don't build-depend on libjack0.100.0-dev or build jack module
      packages,
    + Update pulseaudio's Recommends and Suggests to accomodate
      existing promoted main packages,
    + Explicitly mention pasuspender in pulseaudio-utils's long
      description,
    + Add Vcs-Bzr URI,
    + Adhere to DebianMaintainerField;
  - debian/rules: Use multiuser for update-rc.d;
  - debian/patches/series: Retain the exclusion of
    0001-Set-ESD-socket-to-tmp-.esd-socket-to-match-up-with.patch.
* Dropped Ubuntu-specific change (absorbed into Debian source):
  debian/patches/0002-Double-esound-maximum-sample-size.patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id$ */
 
2
 
 
3
/***
 
4
  This file is part of PulseAudio.
 
5
 
 
6
  Copyright 2004-2006 Lennart Poettering
 
7
  Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
 
8
 
 
9
  PulseAudio is free software; you can redistribute it and/or modify
 
10
  it under the terms of the GNU Lesser General Public License as published
 
11
  by the Free Software Foundation; either version 2 of the License,
 
12
  or (at your option) any later version.
 
13
 
 
14
  PulseAudio is distributed in the hope that it will be useful, but
 
15
  WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
17
  General Public License for more details.
 
18
 
 
19
  You should have received a copy of the GNU Lesser General Public License
 
20
  along with PulseAudio; if not, write to the Free Software
 
21
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
22
  USA.
 
23
***/
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#include <config.h>
 
27
#endif
 
28
 
 
29
#include <unistd.h>
 
30
#include <stdlib.h>
 
31
#include <inttypes.h>
 
32
 
 
33
#include <dbus/dbus.h>
 
34
#include <polkit-dbus/polkit-dbus.h>
 
35
 
 
36
#include <pulsecore/log.h>
 
37
#include <pulsecore/macro.h>
 
38
 
 
39
#include "polkit.h"
 
40
 
 
41
static pa_bool_t show_grant_dialog(const char *action_id) {
 
42
    DBusError dbus_error;
 
43
    DBusConnection *bus = NULL;
 
44
    DBusMessage *m = NULL, *reply = NULL;
 
45
    pa_bool_t r = FALSE;
 
46
    uint32_t xid = 0;
 
47
    int verdict;
 
48
 
 
49
    dbus_error_init(&dbus_error);
 
50
 
 
51
    if (!(bus = dbus_bus_get(DBUS_BUS_SESSION, &dbus_error))) {
 
52
        pa_log_error("Cannot connect to session bus: %s", dbus_error.message);
 
53
        goto finish;
 
54
    }
 
55
 
 
56
    if (!(m = dbus_message_new_method_call("org.gnome.PolicyKit", "/org/gnome/PolicyKit/Manager", "org.gnome.PolicyKit.Manager", "ShowDialog"))) {
 
57
        pa_log_error("Failed to allocate D-Bus message.");
 
58
        goto finish;
 
59
    }
 
60
 
 
61
    if (!(dbus_message_append_args(m, DBUS_TYPE_STRING, &action_id, DBUS_TYPE_UINT32, &xid, DBUS_TYPE_INVALID))) {
 
62
        pa_log_error("Failed to append arguments to D-Bus message.");
 
63
        goto finish;
 
64
    }
 
65
 
 
66
    if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &dbus_error))) {
 
67
        pa_log_warn("Failed to show grant dialog: %s", dbus_error.message);
 
68
        goto finish;
 
69
    }
 
70
 
 
71
    if (!(dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_BOOLEAN, &verdict, DBUS_TYPE_INVALID))) {
 
72
        pa_log_warn("Malformed response from grant manager: %s", dbus_error.message);
 
73
        goto finish;
 
74
    }
 
75
 
 
76
    r = !!verdict;
 
77
 
 
78
finish:
 
79
 
 
80
    if (bus)
 
81
        dbus_connection_unref(bus);
 
82
 
 
83
    dbus_error_free(&dbus_error);
 
84
 
 
85
    if (m)
 
86
        dbus_message_unref(m);
 
87
 
 
88
    if (reply)
 
89
        dbus_message_unref(reply);
 
90
 
 
91
    return r;
 
92
}
 
93
 
 
94
int pa_polkit_check(const char *action_id) {
 
95
    int ret = -1;
 
96
    DBusError dbus_error;
 
97
    DBusConnection *bus = NULL;
 
98
    PolKitCaller *caller = NULL;
 
99
    PolKitAction *action = NULL;
 
100
    PolKitContext *context = NULL;
 
101
    PolKitError *polkit_error = NULL;
 
102
    PolKitSession *session = NULL;
 
103
    PolKitResult polkit_result;
 
104
 
 
105
    dbus_error_init(&dbus_error);
 
106
 
 
107
    if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error))) {
 
108
        pa_log_error("Cannot connect to system bus: %s", dbus_error.message);
 
109
        goto finish;
 
110
    }
 
111
 
 
112
    if (!(caller = polkit_caller_new_from_pid(bus, getpid(), &dbus_error))) {
 
113
        pa_log_error("Cannot get caller from PID: %s", dbus_error.message);
 
114
        goto finish;
 
115
    }
 
116
 
 
117
    /* This function is called when PulseAudio is called SUID root. We
 
118
     * want to authenticate the real user that called us and not the
 
119
     * effective user we gained through being SUID root. Hence we
 
120
     * overwrite the UID caller data here explicitly, just for
 
121
     * paranoia. In fact PolicyKit should fill in the UID here anyway
 
122
     * -- an not the EUID or any other user id. */
 
123
 
 
124
    if (!(polkit_caller_set_uid(caller, getuid()))) {
 
125
        pa_log_error("Cannot set UID on caller object.");
 
126
        goto finish;
 
127
    }
 
128
 
 
129
    if (!(polkit_caller_get_ck_session(caller, &session))) {
 
130
        pa_log_error("Failed to get CK session.");
 
131
        goto finish;
 
132
    }
 
133
 
 
134
    /* We need to overwrite the UID in both the caller and the session
 
135
     * object */
 
136
 
 
137
    if (!(polkit_session_set_uid(session, getuid()))) {
 
138
        pa_log_error("Cannot set UID on session object.");
 
139
        goto finish;
 
140
    }
 
141
 
 
142
    if (!(action = polkit_action_new())) {
 
143
        pa_log_error("Cannot allocate PolKitAction.");
 
144
        goto finish;
 
145
    }
 
146
 
 
147
    if (!polkit_action_set_action_id(action, action_id)) {
 
148
        pa_log_error("Cannot set action_id");
 
149
        goto finish;
 
150
    }
 
151
 
 
152
    if (!(context = polkit_context_new())) {
 
153
        pa_log_error("Cannot allocate PolKitContext.");
 
154
        goto finish;
 
155
    }
 
156
 
 
157
    if (!polkit_context_init(context, &polkit_error)) {
 
158
        pa_log_error("Cannot initialize PolKitContext: %s", polkit_error_get_error_message(polkit_error));
 
159
        goto finish;
 
160
    }
 
161
 
 
162
    for (;;) {
 
163
 
 
164
#ifdef HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
 
165
        polkit_result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error);
 
166
 
 
167
        if (polkit_error_is_set(polkit_error)) {
 
168
            pa_log_error("Could not determine whether caller is authorized: %s", polkit_error_get_error_message(polkit_error));
 
169
            goto finish;
 
170
        }
 
171
#else
 
172
 
 
173
        polkit_result = polkit_context_can_caller_do_action(context, action, caller);
 
174
 
 
175
#endif
 
176
 
 
177
        if (polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
 
178
            polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
 
179
            polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
 
180
#ifdef POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT
 
181
            polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
 
182
#endif
 
183
            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
 
184
            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
 
185
            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS
 
186
#ifdef POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
 
187
            || polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
 
188
#endif
 
189
        ) {
 
190
 
 
191
            if (show_grant_dialog(action_id))
 
192
                continue;
 
193
        }
 
194
 
 
195
        break;
 
196
    }
 
197
 
 
198
    if (polkit_result != POLKIT_RESULT_YES && polkit_result != POLKIT_RESULT_NO)
 
199
        pa_log_warn("PolicyKit responded with '%s'", polkit_result_to_string_representation(polkit_result));
 
200
 
 
201
    ret = polkit_result == POLKIT_RESULT_YES;
 
202
 
 
203
finish:
 
204
 
 
205
    if (caller)
 
206
        polkit_caller_unref(caller);
 
207
 
 
208
    if (action)
 
209
        polkit_action_unref(action);
 
210
 
 
211
    if (context)
 
212
        polkit_context_unref(context);
 
213
 
 
214
    if (bus)
 
215
        dbus_connection_unref(bus);
 
216
 
 
217
    dbus_error_free(&dbus_error);
 
218
 
 
219
    if (polkit_error)
 
220
        polkit_error_free(polkit_error);
 
221
 
 
222
    return ret;
 
223
}