polkitbackendauthority.c 48.5 KB
Newer Older
David Zeuthen's avatar
David Zeuthen committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Copyright (C) 2008 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: David Zeuthen <davidz@redhat.com>
 */

22 23 24 25
#include "config.h"
#include <errno.h>
#include <pwd.h>
#include <string.h>
26

27
#include <polkit/polkit.h>
28
#include <polkit/polkitprivate.h>
29 30 31 32

#include <polkitlocal/polkitlocal.h>
#include <polkitlocal/polkitlocalprivate.h>

33
#include "polkitbackendauthority.h"
34
#include "polkitbackendactionlookup.h"
35
#include "polkitbackendlocalauthority.h"
David Zeuthen's avatar
David Zeuthen committed
36

37 38
#include "polkitbackendprivate.h"

39 40 41 42 43 44 45 46 47 48 49
/**
 * SECTION:polkitbackendauthority
 * @title: PolkitBackendAuthority
 * @short_description: Abstract base class for authority backends
 * @stability: Unstable
 * @see_also: PolkitBackendLocalAuthority
 *
 * To implement an authority backend, simply subclass #PolkitBackendAuthority
 * and implement the required VFuncs.
 */

50 51 52 53 54 55 56 57
enum
{
  CHANGED_SIGNAL,
  LAST_SIGNAL,
};

static guint signals[LAST_SIGNAL] = {0};

58
G_DEFINE_ABSTRACT_TYPE (PolkitBackendAuthority, polkit_backend_authority, G_TYPE_OBJECT);
David Zeuthen's avatar
David Zeuthen committed
59

60 61 62 63
static void
polkit_backend_authority_init (PolkitBackendAuthority *local_authority)
{
}
David Zeuthen's avatar
David Zeuthen committed
64

65 66 67
static void
polkit_backend_authority_class_init (PolkitBackendAuthorityClass *klass)
{
68 69 70 71
  /**
   * PolkitBackendAuthority::changed:
   * @authority: A #PolkitBackendAuthority.
   *
72
   * Emitted when actions and/or authorizations change.
73 74 75 76 77 78 79 80 81 82
   */
  signals[CHANGED_SIGNAL] = g_signal_new ("changed",
                                          POLKIT_BACKEND_TYPE_AUTHORITY,
                                          G_SIGNAL_RUN_LAST,
                                          0,                      /* class offset     */
                                          NULL,                   /* accumulator      */
                                          NULL,                   /* accumulator data */
                                          g_cclosure_marshal_VOID__VOID,
                                          G_TYPE_NONE,
                                          0);
83
}
David Zeuthen's avatar
David Zeuthen committed
84

85 86 87 88 89 90 91 92 93 94
void
polkit_backend_authority_system_bus_name_owner_changed (PolkitBackendAuthority   *authority,
                                                        const gchar              *name,
                                                        const gchar              *old_owner,
                                                        const gchar              *new_owner)
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

95 96
  if (klass->system_bus_name_owner_changed != NULL)
    klass->system_bus_name_owner_changed (authority, name, old_owner, new_owner);
97 98
}

99 100 101 102 103 104 105 106 107 108 109 110
/**
 * polkit_backend_authority_enumerate_actions:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
 * @locale: The locale to retrieve descriptions for.
 * @error: Return location for error or %NULL.
 *
 * Retrieves all registered actions.
 *
 * Returns: A list of #PolkitActionDescription objects or %NULL if @error is set. The returned list
 * should be freed with g_list_free() after each element have been freed with g_object_unref().
 **/
David Zeuthen's avatar
David Zeuthen committed
111
GList *
112
polkit_backend_authority_enumerate_actions (PolkitBackendAuthority   *authority,
David Zeuthen's avatar
David Zeuthen committed
113
                                            PolkitSubject            *caller,
114
                                            const gchar              *locale,
David Zeuthen's avatar
David Zeuthen committed
115
                                            GError                  **error)
116 117 118 119 120
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

121 122 123 124 125 126 127 128 129 130 131 132 133
  if (klass->enumerate_actions == NULL)
    {
      g_warning ("enumerate_actions is not implemented (it is not optional)");
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported (bug in backend)");
      return NULL;
    }
  else
    {
      return klass->enumerate_actions (authority, caller, locale, error);
    }
134
}
David Zeuthen's avatar
David Zeuthen committed
135

136 137 138 139 140 141 142 143 144 145 146
/**
 * polkit_backend_authority_enumerate_users:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
 * @error: Return location for error or %NULL.
 *
 * Enumerates all users known by @authority.
 *
 * Returns: A list of #PolkitIdentity objects or %NULL if @error is set. The returned list
 * should be freed with g_list_free() after each element have been freed with g_object_unref().
 **/
David Zeuthen's avatar
David Zeuthen committed
147
GList *
148
polkit_backend_authority_enumerate_users (PolkitBackendAuthority   *authority,
David Zeuthen's avatar
David Zeuthen committed
149 150
                                          PolkitSubject            *caller,
                                          GError                  **error)
151 152 153 154 155
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

156 157 158 159 160 161 162 163 164 165 166 167
  if (klass->enumerate_users == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported");
      return NULL;
    }
  else
    {
      return klass->enumerate_users (authority, caller, error);
    }
168 169
}

170 171 172 173 174 175 176 177 178 179 180
/**
 * polkit_backend_authority_enumerate_groups:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
 * @error: Return location for error or %NULL.
 *
 * Enumerates all groups known by @authority.
 *
 * Returns: A list of #PolkitIdentity objects or %NULL if @error is set. The returned list
 * should be freed with g_list_free() after each element have been freed with g_object_unref().
 **/
David Zeuthen's avatar
David Zeuthen committed
181
GList *
182
polkit_backend_authority_enumerate_groups (PolkitBackendAuthority   *authority,
David Zeuthen's avatar
David Zeuthen committed
183 184
                                           PolkitSubject            *caller,
                                           GError                  **error)
185 186 187 188 189
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

190 191 192 193 194 195 196 197 198 199 200 201
  if (klass->enumerate_groups == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported");
      return NULL;
    }
  else
    {
      return klass->enumerate_groups (authority, caller, error);
    }
202
}
203

204 205
/* ---------------------------------------------------------------------------------------------------- */

206 207 208 209 210 211
/**
 * polkit_backend_authority_check_authorization:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
 * @subject: A #PolkitSubject.
 * @action_id: The action to check for.
212
 * @details: Details about the action or %NULL.
213 214 215 216 217 218 219 220 221 222 223 224
 * @flags: A set of #PolkitCheckAuthorizationFlags.
 * @cancellable: A #GCancellable.
 * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
 * @user_data: The data to pass to @callback.
 *
 * Asynchronously checks if @subject is authorized to perform the action represented
 * by @action_id.
 *
 * When the operation is finished, @callback will be invoked. You can then
 * call polkit_backend_authority_check_authorization_finish() to get the result of
 * the operation.
 **/
225
void
226
polkit_backend_authority_check_authorization (PolkitBackendAuthority        *authority,
David Zeuthen's avatar
David Zeuthen committed
227
                                              PolkitSubject                 *caller,
228 229
                                              PolkitSubject                 *subject,
                                              const gchar                   *action_id,
230
                                              PolkitDetails                 *details,
231
                                              PolkitCheckAuthorizationFlags  flags,
David Zeuthen's avatar
David Zeuthen committed
232 233 234
                                              GCancellable                  *cancellable,
                                              GAsyncReadyCallback            callback,
                                              gpointer                       user_data)
235 236 237 238 239
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
  if (klass->check_authorization == NULL)
    {
      GSimpleAsyncResult *simple;

      g_warning ("check_authorization is not implemented (it is not optional)");

      simple = g_simple_async_result_new_error (G_OBJECT (authority),
                                                callback,
                                                user_data,
                                                POLKIT_ERROR,
                                                POLKIT_ERROR_NOT_SUPPORTED,
                                                "Operation not supported (bug in backend)");
      g_simple_async_result_complete (simple);
      g_object_unref (simple);
    }
  else
    {
257
      klass->check_authorization (authority, caller, subject, action_id, details, flags, cancellable, callback, user_data);
258
    }
259
}
260

261 262 263 264 265 266 267 268
/**
 * polkit_backend_authority_check_authorization_finish:
 * @authority: A #PolkitBackendAuthority.
 * @res: A #GAsyncResult obtained from the callback.
 * @error: Return location for error or %NULL.
 *
 * Finishes checking if a subject is authorized for an action.
 *
269
 * Returns: A #PolkitAuthorizationResult or %NULL if @error is set. Free with g_object_unref().
270
 **/
271
PolkitAuthorizationResult *
David Zeuthen's avatar
David Zeuthen committed
272 273 274 275 276 277 278 279
polkit_backend_authority_check_authorization_finish (PolkitBackendAuthority  *authority,
                                                     GAsyncResult            *res,
                                                     GError                 **error)
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

280 281 282 283
  if (klass->check_authorization_finish == NULL)
    {
      g_warning ("check_authorization_finish is not implemented (it is not optional)");
      g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
284
      return NULL;
285 286 287 288 289
    }
  else
    {
      return klass->check_authorization_finish (authority, res, error);
    }
David Zeuthen's avatar
David Zeuthen committed
290 291
}

292 293
/* ---------------------------------------------------------------------------------------------------- */

294 295 296 297 298 299 300 301 302
/**
 * polkit_backend_authority_enumerate_authorizations:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
 * @identity: The identity to retrieve authorizations from.
 * @error: Return location for error or %NULL.
 *
 * Retrieves all authorizations for @identity.
 *
303
 * Returns: A list of #PolkitLocalAuthorization objects or %NULL if @error is set. The returned list
304 305
 * should be freed with g_list_free() after each element have been freed with g_object_unref().
 **/
David Zeuthen's avatar
David Zeuthen committed
306
GList *
307
polkit_backend_authority_enumerate_authorizations  (PolkitBackendAuthority    *authority,
David Zeuthen's avatar
David Zeuthen committed
308
                                                    PolkitSubject             *caller,
309
                                                    PolkitIdentity            *identity,
David Zeuthen's avatar
David Zeuthen committed
310
                                                    GError                   **error)
311 312 313 314 315
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

316 317 318 319 320 321 322 323 324 325 326 327
  if (klass->enumerate_authorizations == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported");
      return NULL;
    }
  else
    {
      return klass->enumerate_authorizations (authority, caller, identity, error);
    }
328 329
}

330 331 332 333 334 335 336 337 338 339 340 341
/**
 * polkit_backend_authority_add_authorization:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
 * @identity: The identity to add @authorization to.
 * @authorization: The authorization to add.
 * @error: Return location for error or %NULL.
 *
 * Adds @authorization to @identity.
 *
 * Returns: %TRUE if the operation succeeded or %FALSE if @error is set.
 **/
David Zeuthen's avatar
David Zeuthen committed
342
gboolean
343
polkit_backend_authority_add_authorization  (PolkitBackendAuthority    *authority,
David Zeuthen's avatar
David Zeuthen committed
344
                                             PolkitSubject             *caller,
345
                                             PolkitIdentity            *identity,
346
                                             PolkitLocalAuthorization       *authorization,
David Zeuthen's avatar
David Zeuthen committed
347
                                             GError                   **error)
348 349 350 351 352
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

353 354 355 356 357 358 359 360 361 362 363 364
  if (klass->add_authorization == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported");
      return FALSE;
    }
  else
    {
      return klass->add_authorization (authority, caller, identity, authorization, error);
    }
365 366
}

367 368 369 370 371 372 373 374 375 376 377 378
/**
 * polkit_backend_authority_remove_authorization:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
 * @identity: The identity to remove @authorization from.
 * @authorization: The authorization to remove.
 * @error: Return location for error or %NULL.
 *
 * Removes @authorization from @identity.
 *
 * Returns: %TRUE if the operation succeeded or %FALSE if @error is set.
 **/
David Zeuthen's avatar
David Zeuthen committed
379
gboolean
380
polkit_backend_authority_remove_authorization  (PolkitBackendAuthority    *authority,
David Zeuthen's avatar
David Zeuthen committed
381
                                                PolkitSubject             *caller,
382
                                                PolkitIdentity            *identity,
383
                                                PolkitLocalAuthorization       *authorization,
David Zeuthen's avatar
David Zeuthen committed
384
                                                GError                   **error)
385 386 387 388 389
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

390 391 392 393 394 395 396 397 398 399 400 401
  if (klass->remove_authorization == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported");
      return FALSE;
    }
  else
    {
      return klass->remove_authorization (authority, caller, identity, authorization, error);
    }
402
}
403

404 405 406 407
/**
 * polkit_backend_authority_register_authentication_agent:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
408
 * @session_id: The identifier of the session to register for or %NULL for the session of the caller.
409
 * @locale: The locale of the authentication agent.
410 411 412 413 414 415 416
 * @object_path: The object path for the authentication agent.
 * @error: Return location for error or %NULL.
 *
 * Registers an authentication agent.
 *
 * Returns: %TRUE if the authentication agent was successfully registered, %FALSE if @error is set.
 **/
David Zeuthen's avatar
David Zeuthen committed
417
gboolean
418
polkit_backend_authority_register_authentication_agent (PolkitBackendAuthority    *authority,
David Zeuthen's avatar
David Zeuthen committed
419
                                                        PolkitSubject             *caller,
420
                                                        const gchar               *session_id,
421
                                                        const gchar               *locale,
422
                                                        const gchar               *object_path,
David Zeuthen's avatar
David Zeuthen committed
423
                                                        GError                   **error)
424 425 426 427 428
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

429 430 431 432 433 434 435 436 437 438
  if (klass->register_authentication_agent == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported");
      return FALSE;
    }
  else
    {
439
      return klass->register_authentication_agent (authority, caller, session_id, locale, object_path, error);
440
    }
441 442
}

443 444 445 446
/**
 * polkit_backend_authority_unregister_authentication_agent:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
447
 * @session_id: The identifier of the session the agent is registered at or %NULL for the session of the caller.
448 449 450 451 452 453 454
 * @object_path: The object path that the authentication agent is registered at.
 * @error: Return location for error or %NULL.
 *
 * Unregisters an authentication agent.
 *
 * Returns: %TRUE if the authentication agent was successfully unregistered, %FALSE if @error is set.
 **/
David Zeuthen's avatar
David Zeuthen committed
455
gboolean
456
polkit_backend_authority_unregister_authentication_agent (PolkitBackendAuthority    *authority,
David Zeuthen's avatar
David Zeuthen committed
457
                                                          PolkitSubject             *caller,
458
                                                          const gchar               *session_id,
459
                                                          const gchar               *object_path,
David Zeuthen's avatar
David Zeuthen committed
460
                                                          GError                   **error)
461 462 463 464 465
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

466 467 468 469 470 471 472 473 474 475
  if (klass->unregister_authentication_agent == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported");
      return FALSE;
    }
  else
    {
476
      return klass->unregister_authentication_agent (authority, caller, session_id, object_path, error);
477
    }
478 479
}

480 481 482 483 484 485 486 487 488 489 490 491 492
/**
 * polkit_backend_authority_authentication_agent_response:
 * @authority: A #PolkitBackendAuthority.
 * @caller: The system bus name that initiated the query.
 * @cookie: The cookie passed to the authentication agent from the authority.
 * @identity: The identity that was authenticated.
 * @error: Return location for error or %NULL.
 *
 * Provide response that @identity successfully authenticated for the
 * authentication request identified by @cookie.
 *
 * Returns: %TRUE if @authority acknowledged the call, %FALSE if @error is set.
 **/
David Zeuthen's avatar
David Zeuthen committed
493
gboolean
494
polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority    *authority,
David Zeuthen's avatar
David Zeuthen committed
495
                                                        PolkitSubject             *caller,
496 497
                                                        const gchar               *cookie,
                                                        PolkitIdentity            *identity,
David Zeuthen's avatar
David Zeuthen committed
498
                                                        GError                   **error)
499 500 501 502 503
{
  PolkitBackendAuthorityClass *klass;

  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);

504 505 506 507 508 509 510 511 512 513 514 515
  if (klass->authentication_agent_response == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Operation not supported");
      return FALSE;
    }
  else
    {
      return klass->authentication_agent_response (authority, caller, cookie, identity, error);
    }
516 517
}

518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
/* ---------------------------------------------------------------------------------------------------- */

#define TYPE_SERVER         (server_get_type ())
#define SERVER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_SERVER, Server))
#define SERVER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_SERVER, ServerClass))
#define SERVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_SERVER,ServerClass))
#define IS_SERVER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_SERVER))
#define IS_SERVER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_SERVER))

typedef struct _Server Server;
typedef struct _ServerClass ServerClass;

GType server_get_type (void) G_GNUC_CONST;

struct _Server
{
  GObject parent_instance;

  PolkitBackendAuthority *authority;

  EggDBusConnection *system_bus;

  EggDBusObjectProxy *bus_proxy;

  EggDBusBus *bus;

  gulong name_owner_changed_id;

  gulong authority_changed_id;

  gchar *well_known_name;
549 550

  GHashTable *cancellation_id_to_cancellable;
551 552 553 554 555 556 557 558
};

struct _ServerClass
{
  GObjectClass parent_class;
};

static void authority_iface_init         (_PolkitAuthorityIface        *authority_iface);
559
static void local_authority_iface_init (_PolkitLocalAuthorityIface *local_authority_iface);
560 561 562

G_DEFINE_TYPE_WITH_CODE (Server, server, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (_POLKIT_TYPE_AUTHORITY, authority_iface_init)
563
                         G_IMPLEMENT_INTERFACE (_POLKIT_TYPE_LOCAL_AUTHORITY, local_authority_iface_init)
564 565 566
                         );

static void
567
server_init (Server *server)
568
{
569 570 571 572
  server->cancellation_id_to_cancellable = g_hash_table_new_full (g_str_hash,
                                                                  g_str_equal,
                                                                  g_free,
                                                                  g_object_unref);
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
}

static void
server_finalize (GObject *object)
{
  Server *server;

  server = SERVER (object);

  g_free (server->well_known_name);

  /* TODO: release well_known_name if not NULL */

  g_signal_handler_disconnect (server->bus, server->name_owner_changed_id);

  g_object_unref (server->bus_proxy);

  g_object_unref (server->system_bus);

  g_signal_handler_disconnect (server->authority, server->authority_changed_id);

594
  g_hash_table_unref (server->cancellation_id_to_cancellable);
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
}

static void
server_class_init (ServerClass *klass)
{
  GObjectClass *gobject_class;

  gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->finalize = server_finalize;
}

static void
name_owner_changed (EggDBusBus *instance,
                    gchar      *name,
                    gchar      *old_owner,
                    gchar      *new_owner,
                    Server     *server)
{
  polkit_backend_authority_system_bus_name_owner_changed (server->authority, name, old_owner, new_owner);
}

static void
authority_changed (PolkitBackendAuthority *authority,
                   Server                 *server)
{
  _polkit_authority_emit_signal_changed (_POLKIT_AUTHORITY (server), NULL);
}

/* ---------------------------------------------------------------------------------------------------- */

static void
authority_handle_enumerate_actions (_PolkitAuthority        *instance,
                                    const gchar             *locale,
                                    EggDBusMethodInvocation *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
632 633 634 635 636
  PolkitSubject *caller;
  EggDBusArraySeq *array;
  GError *error;
  GList *actions;
  GList *l;
637

David Zeuthen's avatar
David Zeuthen committed
638 639 640
  error = NULL;
  caller = NULL;
  actions = NULL;
641

David Zeuthen's avatar
David Zeuthen committed
642
  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
643

David Zeuthen's avatar
David Zeuthen committed
644 645 646 647 648 649 650 651 652 653
  actions = polkit_backend_authority_enumerate_actions (server->authority,
                                                        caller,
                                                        locale,
                                                        &error);
  if (error != NULL)
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668

  array = egg_dbus_array_seq_new (G_TYPE_OBJECT, //_POLKIT_TYPE_ACTION_DESCRIPTION,
                                  (GDestroyNotify) g_object_unref,
                                  NULL,
                                  NULL);

  for (l = actions; l != NULL; l = l->next)
    {
      PolkitActionDescription *ad = POLKIT_ACTION_DESCRIPTION (l->data);
      _PolkitActionDescription *real;

      real = polkit_action_description_get_real (ad);
      egg_dbus_array_seq_add (array, real);
    }

David Zeuthen's avatar
David Zeuthen committed
669
  _polkit_authority_handle_enumerate_actions_finish (method_invocation, array);
670 671 672

  g_object_unref (array);

David Zeuthen's avatar
David Zeuthen committed
673
 out:
674 675
  g_list_foreach (actions, (GFunc) g_object_unref, NULL);
  g_list_free (actions);
David Zeuthen's avatar
David Zeuthen committed
676
  g_object_unref (caller);
677 678 679 680 681
}

/* ---------------------------------------------------------------------------------------------------- */

static void
682
local_authority_handle_enumerate_users (_PolkitLocalAuthority *instance,
683 684 685
                                          EggDBusMethodInvocation *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
686 687 688 689 690
  PolkitSubject *caller;
  EggDBusArraySeq *array;
  GError *error;
  GList *identities;
  GList *l;
691

David Zeuthen's avatar
David Zeuthen committed
692
  error = NULL;
693

David Zeuthen's avatar
David Zeuthen committed
694
  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
695

David Zeuthen's avatar
David Zeuthen committed
696 697 698 699 700 701 702 703 704
  identities = polkit_backend_authority_enumerate_users (server->authority,
                                                         caller,
                                                         &error);
  if (error != NULL)
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
705 706 707 708 709 710

  array = egg_dbus_array_seq_new (G_TYPE_OBJECT, //_POLKIT_TYPE_IDENTITY,
                                  (GDestroyNotify) g_object_unref,
                                  NULL,
                                  NULL);

David Zeuthen's avatar
David Zeuthen committed
711
  for (l = identities; l != NULL; l = l->next)
712 713 714 715 716 717 718 719
    {
      PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
      _PolkitIdentity *real;

      real = polkit_identity_get_real (identity);
      egg_dbus_array_seq_add (array, real);
    }

720
  _polkit_local_authority_handle_enumerate_users_finish (method_invocation, array);
721 722 723

  g_object_unref (array);

David Zeuthen's avatar
David Zeuthen committed
724 725 726 727
 out:

  g_list_foreach (identities, (GFunc) g_object_unref, NULL);
  g_list_free (identities);
728

David Zeuthen's avatar
David Zeuthen committed
729
  g_object_unref (caller);
730 731 732 733 734
}

/* ---------------------------------------------------------------------------------------------------- */

static void
735
local_authority_handle_enumerate_groups (_PolkitLocalAuthority *instance,
736 737 738
                                           EggDBusMethodInvocation *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
739 740 741 742 743
  PolkitSubject *caller;
  EggDBusArraySeq *array;
  GError *error;
  GList *identities;
  GList *l;
744

David Zeuthen's avatar
David Zeuthen committed
745
  error = NULL;
746

David Zeuthen's avatar
David Zeuthen committed
747
  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
748

David Zeuthen's avatar
David Zeuthen committed
749 750 751 752 753 754 755 756 757
  identities = polkit_backend_authority_enumerate_groups (server->authority,
                                                          caller,
                                                          &error);
  if (error != NULL)
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
758 759 760 761 762 763

  array = egg_dbus_array_seq_new (G_TYPE_OBJECT, //_POLKIT_TYPE_IDENTITY,
                                  (GDestroyNotify) g_object_unref,
                                  NULL,
                                  NULL);

David Zeuthen's avatar
David Zeuthen committed
764
  for (l = identities; l != NULL; l = l->next)
765 766 767 768 769 770 771 772
    {
      PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
      _PolkitIdentity *real;

      real = polkit_identity_get_real (identity);
      egg_dbus_array_seq_add (array, real);
    }

773
  _polkit_local_authority_handle_enumerate_groups_finish (method_invocation, array);
774 775 776

  g_object_unref (array);

David Zeuthen's avatar
David Zeuthen committed
777 778 779 780
 out:

  g_list_foreach (identities, (GFunc) g_object_unref, NULL);
  g_list_free (identities);
781

David Zeuthen's avatar
David Zeuthen committed
782
  g_object_unref (caller);
783 784 785 786
}

/* ---------------------------------------------------------------------------------------------------- */

David Zeuthen's avatar
David Zeuthen committed
787 788 789 790 791 792
static void
check_auth_cb (GObject      *source_object,
               GAsyncResult *res,
               gpointer      user_data)
{
  EggDBusMethodInvocation *method_invocation = EGG_DBUS_METHOD_INVOCATION (user_data);
793
  const gchar *full_cancellation_id;
794
  PolkitAuthorizationResult *result;
David Zeuthen's avatar
David Zeuthen committed
795 796 797 798 799 800
  GError *error;

  error = NULL;
  result = polkit_backend_authority_check_authorization_finish (POLKIT_BACKEND_AUTHORITY (source_object),
                                                                res,
                                                                &error);
801 802 803 804 805 806 807 808 809

  full_cancellation_id = g_object_get_data (G_OBJECT (method_invocation), "cancellation-id");
  if (full_cancellation_id != NULL)
    {
      Server *server;
      server = SERVER (g_object_get_data (G_OBJECT (method_invocation), "server"));
      g_hash_table_remove (server->cancellation_id_to_cancellable, full_cancellation_id);
    }

David Zeuthen's avatar
David Zeuthen committed
810 811 812 813 814 815 816
  if (error != NULL)
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
    }
  else
    {
817 818 819
      _PolkitAuthorizationResult *real_result;
      real_result = polkit_authorization_result_get_real (result);
      _polkit_authority_handle_check_authorization_finish (method_invocation, real_result);
David Zeuthen's avatar
David Zeuthen committed
820
      g_object_unref (real_result);
821
      g_object_unref (result);
David Zeuthen's avatar
David Zeuthen committed
822 823 824
    }
}

825 826 827 828
static void
authority_handle_check_authorization (_PolkitAuthority               *instance,
                                      _PolkitSubject                 *real_subject,
                                      const gchar                    *action_id,
829
                                      EggDBusHashMap                 *real_details,
830
                                      _PolkitCheckAuthorizationFlags  flags,
831
                                      const gchar                    *cancellation_id,
832 833 834
                                      EggDBusMethodInvocation        *method_invocation)
{
  Server *server = SERVER (instance);
835
  const gchar *caller_name;
836
  PolkitSubject *subject;
David Zeuthen's avatar
David Zeuthen committed
837
  PolkitSubject *caller;
838
  GCancellable *cancellable;
839
  PolkitDetails *details;
840

841 842
  caller_name = egg_dbus_method_invocation_get_caller (method_invocation);
  caller = polkit_system_bus_name_new (caller_name);
843 844 845

  subject = polkit_subject_new_for_real (real_subject);

846
  details = polkit_details_new_for_hash (real_details->data);
847

David Zeuthen's avatar
David Zeuthen committed
848 849
  g_object_set_data_full (G_OBJECT (method_invocation), "caller", caller, (GDestroyNotify) g_object_unref);
  g_object_set_data_full (G_OBJECT (method_invocation), "subject", subject, (GDestroyNotify) g_object_unref);
850

851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
  cancellable = NULL;
  if (cancellation_id != NULL && strlen (cancellation_id) > 0)
    {
      gchar *full_cancellation_id;

      full_cancellation_id = g_strdup_printf ("%s-%s", caller_name, cancellation_id);

      if (g_hash_table_lookup (server->cancellation_id_to_cancellable, full_cancellation_id) != NULL)
        {
          egg_dbus_method_invocation_return_error (method_invocation,
                                                   _POLKIT_ERROR,
                                                   _POLKIT_ERROR_CANCELLATION_ID_NOT_UNIQUE,
                                                   "Given cancellation_id %s is already in use for name %s",
                                                   cancellation_id,
                                                   caller_name);
          g_free (full_cancellation_id);
          goto out;
        }

      cancellable = g_cancellable_new ();

      g_hash_table_insert (server->cancellation_id_to_cancellable,
                           full_cancellation_id,
                           cancellable);

      g_object_set_data (G_OBJECT (method_invocation), "server", server);
      g_object_set_data (G_OBJECT (method_invocation), "cancellation-id", full_cancellation_id);
    }

880
  polkit_backend_authority_check_authorization (server->authority,
David Zeuthen's avatar
David Zeuthen committed
881
                                                caller,
882 883
                                                subject,
                                                action_id,
884
                                                details,
885
                                                flags,
886
                                                cancellable,
David Zeuthen's avatar
David Zeuthen committed
887 888
                                                check_auth_cb,
                                                method_invocation);
889
 out:
890
  g_object_unref (details);
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
}

static void
authority_handle_cancel_check_authorization (_PolkitAuthority               *instance,
                                             const gchar                    *cancellation_id,
                                             EggDBusMethodInvocation        *method_invocation)
{
  Server *server = SERVER (instance);
  GCancellable *cancellable;
  const gchar *caller_name;
  gchar *full_cancellation_id;

  caller_name = egg_dbus_method_invocation_get_caller (method_invocation);

  full_cancellation_id = g_strdup_printf ("%s-%s", caller_name, cancellation_id);

  cancellable = g_hash_table_lookup (server->cancellation_id_to_cancellable, full_cancellation_id);
  if (cancellable == NULL)
    {
      egg_dbus_method_invocation_return_error (method_invocation,
                                               _POLKIT_ERROR,
                                               _POLKIT_ERROR_FAILED,
                                               "No such cancellation_id %s for name %s",
                                               cancellation_id,
                                               caller_name);
      goto out;
    }

  g_cancellable_cancel (cancellable);

  _polkit_authority_handle_cancel_check_authorization_finish (method_invocation);

 out:
  g_free (full_cancellation_id);
925 926 927 928 929
}

/* ---------------------------------------------------------------------------------------------------- */

static void
930
local_authority_handle_enumerate_authorizations (_PolkitLocalAuthority        *instance,
931 932 933 934
                                                   _PolkitIdentity                *real_identity,
                                                   EggDBusMethodInvocation        *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
935
  PolkitSubject *caller;
936
  PolkitIdentity *identity;
David Zeuthen's avatar
David Zeuthen committed
937 938 939 940
  EggDBusArraySeq *array;
  GError *error;
  GList *authorizations;
  GList *l;
941

David Zeuthen's avatar
David Zeuthen committed
942
  error = NULL;
943

David Zeuthen's avatar
David Zeuthen committed
944
  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
945

David Zeuthen's avatar
David Zeuthen committed
946
  identity = polkit_identity_new_for_real (real_identity);
947

David Zeuthen's avatar
David Zeuthen committed
948 949 950 951
  authorizations = polkit_backend_authority_enumerate_authorizations (server->authority,
                                                                      caller,
                                                                      identity,
                                                                      &error);
952

David Zeuthen's avatar
David Zeuthen committed
953 954 955 956 957 958
  if (error != NULL)
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
959

David Zeuthen's avatar
David Zeuthen committed
960
  array = egg_dbus_array_seq_new (G_TYPE_OBJECT, //_POLKIT_TYPE_IDENTITY,
961 962 963 964 965 966
                                  (GDestroyNotify) g_object_unref,
                                  NULL,
                                  NULL);

  for (l = authorizations; l != NULL; l = l->next)
    {
967 968
      PolkitLocalAuthorization *authorization = POLKIT_LOCAL_AUTHORIZATION (l->data);
      _PolkitLocalAuthorization *real;
969

970
      real = polkit_local_authorization_get_real (authorization);
971 972 973
      egg_dbus_array_seq_add (array, real);
    }

974
  _polkit_local_authority_handle_enumerate_authorizations_finish (method_invocation, array);
975 976 977

  g_object_unref (array);

David Zeuthen's avatar
David Zeuthen committed
978 979
 out:

980 981 982
  g_list_foreach (authorizations, (GFunc) g_object_unref, NULL);
  g_list_free (authorizations);

David Zeuthen's avatar
David Zeuthen committed
983 984 985
  g_object_unref (caller);

  g_object_unref (identity);
986 987 988 989 990
}

/* ---------------------------------------------------------------------------------------------------- */

static void
991
local_authority_handle_add_authorization (_PolkitLocalAuthority        *instance,
992
                                            _PolkitIdentity                *real_identity,
993
                                            _PolkitLocalAuthorization           *real_authorization,
994 995 996
                                            EggDBusMethodInvocation        *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
997
  PolkitSubject *caller;
998
  PolkitIdentity *identity;
999
  PolkitLocalAuthorization *authorization;
David Zeuthen's avatar
David Zeuthen committed
1000
  GError *error;
1001

David Zeuthen's avatar
David Zeuthen committed
1002 1003

  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
1004 1005 1006

  identity = polkit_identity_new_for_real (real_identity);

1007
  authorization = polkit_local_authorization_new_for_real (real_authorization);
1008

David Zeuthen's avatar
David Zeuthen committed
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
  error = NULL;
  if (!polkit_backend_authority_add_authorization (server->authority,
                                                   caller,
                                                   identity,
                                                   authorization,
                                                   &error))
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
1020

1021
  _polkit_local_authority_handle_add_authorization_finish (method_invocation);
1022

David Zeuthen's avatar
David Zeuthen committed
1023 1024 1025 1026
 out:
  g_object_unref (authorization);
  g_object_unref (identity);
  g_object_unref (caller);
1027 1028 1029 1030 1031
}

/* ---------------------------------------------------------------------------------------------------- */

static void
1032
local_authority_handle_remove_authorization (_PolkitLocalAuthority        *instance,
1033
                                               _PolkitIdentity                *real_identity,
1034
                                               _PolkitLocalAuthorization           *real_authorization,
1035 1036 1037
                                               EggDBusMethodInvocation        *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
1038
  PolkitSubject *caller;
1039
  PolkitIdentity *identity;
1040
  PolkitLocalAuthorization *authorization;
David Zeuthen's avatar
David Zeuthen committed
1041
  GError *error;
1042

David Zeuthen's avatar
David Zeuthen committed
1043 1044

  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
1045 1046 1047

  identity = polkit_identity_new_for_real (real_identity);

1048
  authorization = polkit_local_authorization_new_for_real (real_authorization);
1049

David Zeuthen's avatar
David Zeuthen committed
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
  error = NULL;
  if (!polkit_backend_authority_remove_authorization (server->authority,
                                                      caller,
                                                      identity,
                                                      authorization,
                                                      &error))
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
1061

1062
  _polkit_local_authority_handle_remove_authorization_finish (method_invocation);
1063

David Zeuthen's avatar
David Zeuthen committed
1064 1065 1066 1067
 out:
  g_object_unref (authorization);
  g_object_unref (identity);
  g_object_unref (caller);
1068 1069 1070 1071 1072 1073
}

/* ---------------------------------------------------------------------------------------------------- */

static void
authority_handle_register_authentication_agent (_PolkitAuthority               *instance,
1074
                                                const gchar                    *session_id,
1075
                                                const gchar                    *locale,
1076 1077 1078 1079
                                                const gchar                    *object_path,
                                                EggDBusMethodInvocation        *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
1080 1081
  PolkitSubject *caller;
  GError *error;
1082

David Zeuthen's avatar
David Zeuthen committed
1083
  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
1084

David Zeuthen's avatar
David Zeuthen committed
1085 1086 1087
  error = NULL;
  if (!polkit_backend_authority_register_authentication_agent (server->authority,
                                                               caller,
1088
                                                               session_id,
1089
                                                               locale,
David Zeuthen's avatar
David Zeuthen committed
1090 1091 1092 1093 1094 1095 1096
                                                               object_path,
                                                               &error))
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
1097

David Zeuthen's avatar
David Zeuthen committed
1098 1099 1100 1101
  _polkit_authority_handle_register_authentication_agent_finish (method_invocation);

 out:
  g_object_unref (caller);
1102 1103 1104 1105 1106 1107
}

/* ---------------------------------------------------------------------------------------------------- */

static void
authority_handle_unregister_authentication_agent (_PolkitAuthority               *instance,
1108
                                                  const gchar                    *session_id,
1109 1110 1111 1112
                                                  const gchar                    *object_path,
                                                  EggDBusMethodInvocation        *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
1113 1114
  PolkitSubject *caller;
  GError *error;
1115

David Zeuthen's avatar
David Zeuthen committed
1116
  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
1117

David Zeuthen's avatar
David Zeuthen committed
1118 1119 1120
  error = NULL;
  if (!polkit_backend_authority_unregister_authentication_agent (server->authority,
                                                                 caller,
1121
                                                                 session_id,
David Zeuthen's avatar
David Zeuthen committed
1122 1123 1124 1125 1126 1127 1128
                                                                 object_path,
                                                                 &error))
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
1129

David Zeuthen's avatar
David Zeuthen committed
1130 1131 1132 1133
  _polkit_authority_handle_unregister_authentication_agent_finish (method_invocation);

 out:
  g_object_unref (caller);
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
}

/* ---------------------------------------------------------------------------------------------------- */

static void
authority_handle_authentication_agent_response (_PolkitAuthority               *instance,
                                                const gchar                    *cookie,
                                                _PolkitIdentity                *real_identity,
                                                EggDBusMethodInvocation        *method_invocation)
{
  Server *server = SERVER (instance);
David Zeuthen's avatar
David Zeuthen committed
1145
  PolkitSubject *caller;
1146
  PolkitIdentity *identity;
David Zeuthen's avatar
David Zeuthen committed
1147
  GError *error;
1148 1149 1150

  identity = polkit_identity_new_for_real (real_identity);

David Zeuthen's avatar
David Zeuthen committed
1151
  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
1152

David Zeuthen's avatar
David Zeuthen committed
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
  error = NULL;
  if (!polkit_backend_authority_authentication_agent_response (server->authority,
                                                               caller,
                                                               cookie,
                                                               identity,
                                                               &error))
    {
      egg_dbus_method_invocation_return_gerror (method_invocation, error);
      g_error_free (error);
      goto out;
    }
1164

David Zeuthen's avatar
David Zeuthen committed
1165 1166 1167 1168 1169 1170
  _polkit_authority_handle_authentication_agent_response_finish (method_invocation);

 out:
  g_object_unref (caller);

  g_object_unref (identity);
1171 1172 1173 1174 1175 1176 1177 1178 1179
}

/* ---------------------------------------------------------------------------------------------------- */

static void
authority_iface_init (_PolkitAuthorityIface *authority_iface)
{
  authority_iface->handle_enumerate_actions               = authority_handle_enumerate_actions;
  authority_iface->handle_check_authorization             = authority_handle_check_authorization;
1180
  authority_iface->handle_cancel_check_authorization      = authority_handle_cancel_check_authorization;
1181 1182 1183 1184 1185 1186
  authority_iface->handle_register_authentication_agent   = authority_handle_register_authentication_agent;
  authority_iface->handle_unregister_authentication_agent = authority_handle_unregister_authentication_agent;
  authority_iface->handle_authentication_agent_response   = authority_handle_authentication_agent_response;
}

static void
1187
local_authority_iface_init (_PolkitLocalAuthorityIface *local_authority_iface)
1188
{
1189 1190 1191 1192 1193
  local_authority_iface->handle_enumerate_users                 = local_authority_handle_enumerate_users;
  local_authority_iface->handle_enumerate_groups                = local_authority_handle_enumerate_groups;
  local_authority_iface->handle_enumerate_authorizations        = local_authority_handle_enumerate_authorizations;
  local_authority_iface->handle_add_authorization               = local_authority_handle_add_authorization;
  local_authority_iface->handle_remove_authorization            = local_authority_handle_remove_authorization;
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210