~ubuntu-branches/ubuntu/wily/policykit-1/wily

« back to all changes in this revision

Viewing changes to src/polkitbackend/polkitbackendsessionmonitor-systemd.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2012-01-06 12:28:54 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20120106122854-ib9s0ej8akqiy0lb
Tags: 0.104-1
* New upstream release.
  - Add support for netgroups. (LP: #724052)
* debian/rules: Disable systemd support, continue to work with ConsokeKit.
* 05_revert-admin-identities-unix-group-wheel.patch: Refresh to apply
  cleanly.
* debian/libpolkit-gobject-1-0.symbols: Add new symbols from this new
  release.
* debian/rules: Do not let test failures fail the build. The new test suite
  also runs a test against the system D-BUS/ConsoleKit, which can't work on
  buildds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 Red Hat, Inc.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General
 
15
 * Public License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 *
 
19
 * Author: Matthias Clasen
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
#include <errno.h>
 
24
#include <pwd.h>
 
25
#include <grp.h>
 
26
#include <string.h>
 
27
#include <glib/gstdio.h>
 
28
#include <systemd/sd-login.h>
 
29
#include <stdlib.h>
 
30
 
 
31
#include <polkit/polkit.h>
 
32
#include "polkitbackendsessionmonitor.h"
 
33
 
 
34
/* <internal>
 
35
 * SECTION:polkitbackendsessionmonitor
 
36
 * @title: PolkitBackendSessionMonitor
 
37
 * @short_description: Monitor sessions
 
38
 *
 
39
 * The #PolkitBackendSessionMonitor class is a utility class to track and monitor sessions.
 
40
 */
 
41
 
 
42
typedef struct
 
43
{
 
44
  GSource source;
 
45
  GPollFD pollfd;
 
46
  sd_login_monitor *monitor;
 
47
} SdSource;
 
48
 
 
49
static gboolean
 
50
sd_source_prepare (GSource *source,
 
51
                   gint    *timeout)
 
52
{
 
53
  *timeout = -1;
 
54
  return FALSE;
 
55
}
 
56
 
 
57
static gboolean
 
58
sd_source_check (GSource *source)
 
59
{
 
60
  SdSource *sd_source = (SdSource *)source;
 
61
 
 
62
  return sd_source->pollfd.revents != 0;
 
63
}
 
64
 
 
65
static gboolean
 
66
sd_source_dispatch (GSource     *source,
 
67
                    GSourceFunc  callback,
 
68
                    gpointer     user_data)
 
69
 
 
70
{
 
71
  SdSource *sd_source = (SdSource *)source;
 
72
  gboolean ret;
 
73
 
 
74
  g_warn_if_fail (callback != NULL);
 
75
 
 
76
  ret = (*callback) (user_data);
 
77
 
 
78
  sd_login_monitor_flush (sd_source->monitor);
 
79
 
 
80
  return ret;
 
81
}
 
82
 
 
83
static void
 
84
sd_source_finalize (GSource *source)
 
85
{
 
86
  SdSource *sd_source = (SdSource*)source;
 
87
 
 
88
  sd_login_monitor_unref (sd_source->monitor);
 
89
}
 
90
 
 
91
static GSourceFuncs sd_source_funcs = {
 
92
  sd_source_prepare,
 
93
  sd_source_check,
 
94
  sd_source_dispatch,
 
95
  sd_source_finalize
 
96
};
 
97
 
 
98
static GSource *
 
99
sd_source_new (void)
 
100
{
 
101
  GSource *source;
 
102
  SdSource *sd_source;
 
103
  int ret;
 
104
 
 
105
  source = g_source_new (&sd_source_funcs, sizeof (SdSource));
 
106
  sd_source = (SdSource *)source;
 
107
 
 
108
  if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0)
 
109
    {
 
110
      g_printerr ("Error getting login monitor: %d", ret);
 
111
    }
 
112
  else
 
113
    {
 
114
      sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor);
 
115
      sd_source->pollfd.events = G_IO_IN;
 
116
      g_source_add_poll (source, &sd_source->pollfd);
 
117
    }
 
118
 
 
119
  return source;
 
120
}
 
121
 
 
122
struct _PolkitBackendSessionMonitor
 
123
{
 
124
  GObject parent_instance;
 
125
 
 
126
  GDBusConnection *system_bus;
 
127
 
 
128
  GSource *sd_source;
 
129
};
 
130
 
 
131
struct _PolkitBackendSessionMonitorClass
 
132
{
 
133
  GObjectClass parent_class;
 
134
 
 
135
  void (*changed) (PolkitBackendSessionMonitor *monitor);
 
136
};
 
137
 
 
138
 
 
139
enum
 
140
{
 
141
  CHANGED_SIGNAL,
 
142
  LAST_SIGNAL,
 
143
};
 
144
 
 
145
static guint signals[LAST_SIGNAL] = {0};
 
146
 
 
147
G_DEFINE_TYPE (PolkitBackendSessionMonitor, polkit_backend_session_monitor, G_TYPE_OBJECT);
 
148
 
 
149
/* ---------------------------------------------------------------------------------------------------- */
 
150
 
 
151
static gboolean
 
152
sessions_changed (gpointer user_data)
 
153
{
 
154
  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
 
155
 
 
156
  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
 
157
 
 
158
  return TRUE;
 
159
}
 
160
 
 
161
 
 
162
static void
 
163
polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor)
 
164
{
 
165
  GError *error;
 
166
 
 
167
  error = NULL;
 
168
  monitor->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
169
  if (monitor->system_bus == NULL)
 
170
    {
 
171
      g_printerr ("Error getting system bus: %s", error->message);
 
172
      g_error_free (error);
 
173
    }
 
174
 
 
175
  monitor->sd_source = sd_source_new ();
 
176
  g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
 
177
  g_source_attach (monitor->sd_source, NULL);
 
178
}
 
179
 
 
180
static void
 
181
polkit_backend_session_monitor_finalize (GObject *object)
 
182
{
 
183
  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (object);
 
184
 
 
185
  if (monitor->system_bus != NULL)
 
186
    g_object_unref (monitor->system_bus);
 
187
 
 
188
  if (monitor->sd_source != NULL)
 
189
    {
 
190
      g_source_destroy (monitor->sd_source);
 
191
      g_source_unref (monitor->sd_source);
 
192
    }
 
193
 
 
194
  if (G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize != NULL)
 
195
    G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize (object);
 
196
}
 
197
 
 
198
static void
 
199
polkit_backend_session_monitor_class_init (PolkitBackendSessionMonitorClass *klass)
 
200
{
 
201
  GObjectClass *gobject_class;
 
202
 
 
203
  gobject_class = G_OBJECT_CLASS (klass);
 
204
 
 
205
  gobject_class->finalize = polkit_backend_session_monitor_finalize;
 
206
 
 
207
  /**
 
208
   * PolkitBackendSessionMonitor::changed:
 
209
   * @monitor: A #PolkitBackendSessionMonitor
 
210
   *
 
211
   * Emitted when something changes.
 
212
   */
 
213
  signals[CHANGED_SIGNAL] = g_signal_new ("changed",
 
214
                                          POLKIT_BACKEND_TYPE_SESSION_MONITOR,
 
215
                                          G_SIGNAL_RUN_LAST,
 
216
                                          G_STRUCT_OFFSET (PolkitBackendSessionMonitorClass, changed),
 
217
                                          NULL,                   /* accumulator      */
 
218
                                          NULL,                   /* accumulator data */
 
219
                                          g_cclosure_marshal_VOID__VOID,
 
220
                                          G_TYPE_NONE,
 
221
                                          0);
 
222
}
 
223
 
 
224
PolkitBackendSessionMonitor *
 
225
polkit_backend_session_monitor_new (void)
 
226
{
 
227
  PolkitBackendSessionMonitor *monitor;
 
228
 
 
229
  monitor = POLKIT_BACKEND_SESSION_MONITOR (g_object_new (POLKIT_BACKEND_TYPE_SESSION_MONITOR, NULL));
 
230
 
 
231
  return monitor;
 
232
}
 
233
 
 
234
/* ---------------------------------------------------------------------------------------------------- */
 
235
 
 
236
GList *
 
237
polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor)
 
238
{
 
239
  /* TODO */
 
240
  return NULL;
 
241
}
 
242
 
 
243
/* ---------------------------------------------------------------------------------------------------- */
 
244
 
 
245
/**
 
246
 * polkit_backend_session_monitor_get_user:
 
247
 * @monitor: A #PolkitBackendSessionMonitor.
 
248
 * @subject: A #PolkitSubject.
 
249
 * @error: Return location for error.
 
250
 *
 
251
 * Gets the user corresponding to @subject or %NULL if no user exists.
 
252
 *
 
253
 * Returns: %NULL if @error is set otherwise a #PolkitUnixUser that should be freed with g_object_unref().
 
254
 */
 
255
PolkitIdentity *
 
256
polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor  *monitor,
 
257
                                                     PolkitSubject                *subject,
 
258
                                                     GError                      **error)
 
259
{
 
260
  PolkitIdentity *ret;
 
261
  guint32 uid;
 
262
 
 
263
  ret = NULL;
 
264
 
 
265
  if (POLKIT_IS_UNIX_PROCESS (subject))
 
266
    {
 
267
      uid = polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject));
 
268
      if ((gint) uid == -1)
 
269
        {
 
270
          g_set_error (error,
 
271
                       POLKIT_ERROR,
 
272
                       POLKIT_ERROR_FAILED,
 
273
                       "Unix process subject does not have uid set");
 
274
          goto out;
 
275
        }
 
276
      ret = polkit_unix_user_new (uid);
 
277
    }
 
278
  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
 
279
    {
 
280
      GVariant *result;
 
281
 
 
282
      result = g_dbus_connection_call_sync (monitor->system_bus,
 
283
                                            "org.freedesktop.DBus",
 
284
                                            "/org/freedesktop/DBus",
 
285
                                            "org.freedesktop.DBus",
 
286
                                            "GetConnectionUnixUser",
 
287
                                            g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))),
 
288
                                            G_VARIANT_TYPE ("(u)"),
 
289
                                            G_DBUS_CALL_FLAGS_NONE,
 
290
                                            -1, /* timeout_msec */
 
291
                                            NULL, /* GCancellable */
 
292
                                            error);
 
293
      if (result == NULL)
 
294
        goto out;
 
295
      g_variant_get (result, "(u)", &uid);
 
296
      g_variant_unref (result);
 
297
 
 
298
      ret = polkit_unix_user_new (uid);
 
299
    }
 
300
  else if (POLKIT_IS_UNIX_SESSION (subject))
 
301
    {
 
302
 
 
303
      if (sd_session_get_uid (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject)), &uid) < 0)
 
304
        {
 
305
          g_set_error (error,
 
306
                       POLKIT_ERROR,
 
307
                       POLKIT_ERROR_FAILED,
 
308
                       "Error getting uid for session");
 
309
          goto out;
 
310
        }
 
311
 
 
312
      ret = polkit_unix_user_new (uid);
 
313
    }
 
314
 
 
315
 out:
 
316
  return ret;
 
317
}
 
318
 
 
319
/**
 
320
 * polkit_backend_session_monitor_get_session_for_subject:
 
321
 * @monitor: A #PolkitBackendSessionMonitor.
 
322
 * @subject: A #PolkitSubject.
 
323
 * @error: Return location for error.
 
324
 *
 
325
 * Gets the session corresponding to @subject or %NULL if no session exists.
 
326
 *
 
327
 * Returns: %NULL if @error is set otherwise a #PolkitUnixSession that should be freed with g_object_unref().
 
328
 */
 
329
PolkitSubject *
 
330
polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMonitor *monitor,
 
331
                                                        PolkitSubject               *subject,
 
332
                                                        GError                     **error)
 
333
{
 
334
  PolkitSubject *session;
 
335
 
 
336
  session = NULL;
 
337
 
 
338
  if (POLKIT_IS_UNIX_PROCESS (subject))
 
339
    {
 
340
      gchar *session_id;
 
341
      pid_t pid;
 
342
 
 
343
      pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
 
344
      if (sd_pid_get_session (pid, &session_id) < 0)
 
345
        goto out;
 
346
 
 
347
      session = polkit_unix_session_new (session_id);
 
348
      free (session_id);
 
349
    }
 
350
  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
 
351
    {
 
352
      guint32 pid;
 
353
      gchar *session_id;
 
354
      GVariant *result;
 
355
 
 
356
      result = g_dbus_connection_call_sync (monitor->system_bus,
 
357
                                            "org.freedesktop.DBus",
 
358
                                            "/org/freedesktop/DBus",
 
359
                                            "org.freedesktop.DBus",
 
360
                                            "GetConnectionUnixProcessID",
 
361
                                            g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))),
 
362
                                            G_VARIANT_TYPE ("(u)"),
 
363
                                            G_DBUS_CALL_FLAGS_NONE,
 
364
                                            -1, /* timeout_msec */
 
365
                                            NULL, /* GCancellable */
 
366
                                            error);
 
367
      if (result == NULL)
 
368
        goto out;
 
369
      g_variant_get (result, "(u)", &pid);
 
370
      g_variant_unref (result);
 
371
 
 
372
      if (sd_pid_get_session (pid, &session_id) < 0)
 
373
        goto out;
 
374
 
 
375
      session = polkit_unix_session_new (session_id);
 
376
      free (session_id);
 
377
    }
 
378
  else
 
379
    {
 
380
      g_set_error (error,
 
381
                   POLKIT_ERROR,
 
382
                   POLKIT_ERROR_NOT_SUPPORTED,
 
383
                   "Cannot get user for subject of type %s",
 
384
                   g_type_name (G_TYPE_FROM_INSTANCE (subject)));
 
385
    }
 
386
 
 
387
 out:
 
388
 
 
389
  return session;
 
390
}
 
391
 
 
392
gboolean
 
393
polkit_backend_session_monitor_is_session_local (PolkitBackendSessionMonitor *monitor,
 
394
                                                 PolkitSubject               *session)
 
395
{
 
396
  char *seat;
 
397
 
 
398
  if (!sd_session_get_seat (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)), &seat))
 
399
    {
 
400
      free (seat);
 
401
      return TRUE;
 
402
    }
 
403
 
 
404
  return FALSE;
 
405
}
 
406
 
 
407
 
 
408
gboolean
 
409
polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor,
 
410
                                                  PolkitSubject               *session)
 
411
{
 
412
  return sd_session_is_active (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)));
 
413
}
 
414