Blame src/goaidentity/goaidentityservice.c

Packit Service c6b9b0
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
Packit Service c6b9b0
/*
Packit Service c6b9b0
 * Copyright © 2012 – 2017 Red Hat, Inc.
Packit Service c6b9b0
 *
Packit Service c6b9b0
 * This library is free software; you can redistribute it and/or
Packit Service c6b9b0
 * modify it under the terms of the GNU Lesser General Public
Packit Service c6b9b0
 * License as published by the Free Software Foundation; either
Packit Service c6b9b0
 * version 2 of the License, or (at your option) any later version.
Packit Service c6b9b0
 *
Packit Service c6b9b0
 * This library is distributed in the hope that it will be useful,
Packit Service c6b9b0
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service c6b9b0
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service c6b9b0
 * Lesser General Public License for more details.
Packit Service c6b9b0
 *
Packit Service c6b9b0
 * You should have received a copy of the GNU Lesser General
Packit Service c6b9b0
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit Service c6b9b0
 */
Packit Service c6b9b0
Packit Service c6b9b0
#include "config.h"
Packit Service c6b9b0
#include "goaidentityservice.h"
Packit Service c6b9b0
Packit Service c6b9b0
#include <glib/gi18n.h>
Packit Service c6b9b0
#include <gmodule.h>
Packit Service c6b9b0
Packit Service c6b9b0
#include <glib.h>
Packit Service c6b9b0
#include <glib-object.h>
Packit Service c6b9b0
#include <gio/gio.h>
Packit Service c6b9b0
Packit Service c6b9b0
#include <gcr/gcr.h>
Packit Service c6b9b0
Packit Service c6b9b0
#include <goa/goa.h>
Packit Service c6b9b0
Packit Service c6b9b0
#include "goaidentityenumtypes.h"
Packit Service c6b9b0
#include "goaidentitymanagererror.h"
Packit Service c6b9b0
#include "goaidentityutils.h"
Packit Service c6b9b0
Packit Service c6b9b0
#include "goakerberosidentitymanager.h"
Packit Service c6b9b0
Packit Service c6b9b0
struct _GoaIdentityServicePrivate
Packit Service c6b9b0
{
Packit Service c6b9b0
  GDBusConnection          *connection;
Packit Service c6b9b0
  GDBusObjectManagerServer *object_manager_server;
Packit Service c6b9b0
  guint                     bus_id;
Packit Service c6b9b0
Packit Service c6b9b0
  GoaIdentityManager       *identity_manager;
Packit Service c6b9b0
Packit Service c6b9b0
  GHashTable               *watched_client_connections;
Packit Service c6b9b0
  GHashTable               *key_holders;
Packit Service c6b9b0
  GHashTable               *pending_temporary_account_results;
Packit Service c6b9b0
Packit Service c6b9b0
  GoaClient                *client;
Packit Service c6b9b0
};
Packit Service c6b9b0
Packit Service c6b9b0
static void identity_service_manager_interface_init (GoaIdentityServiceManagerIface *interface);
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
sign_in (GoaIdentityService     *self,
Packit Service c6b9b0
         const char             *identifier,
Packit Service c6b9b0
         gconstpointer           initial_password,
Packit Service c6b9b0
         const char             *preauth_source,
Packit Service c6b9b0
         GoaIdentitySignInFlags  flags,
Packit Service c6b9b0
         GCancellable           *cancellable,
Packit Service c6b9b0
         GAsyncReadyCallback     callback,
Packit Service c6b9b0
         gpointer                user_data);
Packit Service c6b9b0
Packit Service c6b9b0
G_DEFINE_TYPE_WITH_CODE (GoaIdentityService,
Packit Service c6b9b0
                         goa_identity_service,
Packit Service c6b9b0
                         GOA_IDENTITY_SERVICE_TYPE_MANAGER_SKELETON,
Packit Service c6b9b0
                         G_IMPLEMENT_INTERFACE (GOA_IDENTITY_SERVICE_TYPE_MANAGER,
Packit Service c6b9b0
                                                identity_service_manager_interface_init));
Packit Service c6b9b0
Packit Service c6b9b0
static char *
Packit Service c6b9b0
get_object_path_for_identity (GoaIdentityService *self,
Packit Service c6b9b0
                              GoaIdentity        *identity)
Packit Service c6b9b0
{
Packit Service c6b9b0
  const char *identifier;
Packit Service c6b9b0
  char       *escaped_identifier;
Packit Service c6b9b0
  char       *object_path;
Packit Service c6b9b0
Packit Service c6b9b0
  identifier = goa_identity_get_identifier (identity);
Packit Service c6b9b0
  escaped_identifier = goa_identity_utils_escape_object_path (identifier,
Packit Service c6b9b0
                                                              strlen (identifier));
Packit Service c6b9b0
  object_path = g_strdup_printf ("/org/gnome/Identity/Identities/%s", escaped_identifier);
Packit Service c6b9b0
Packit Service c6b9b0
  g_free (escaped_identifier);
Packit Service c6b9b0
  return object_path;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static char *
Packit Service c6b9b0
export_identity (GoaIdentityService *self,
Packit Service c6b9b0
                 GoaIdentity        *identity)
Packit Service c6b9b0
{
Packit Service c6b9b0
  char *object_path;
Packit Service c6b9b0
  GDBusObjectSkeleton *object;
Packit Service c6b9b0
  GDBusInterfaceSkeleton *interface;
Packit Service c6b9b0
Packit Service c6b9b0
  object_path = get_object_path_for_identity (self, identity);
Packit Service c6b9b0
Packit Service c6b9b0
  object = G_DBUS_OBJECT_SKELETON (goa_identity_service_object_skeleton_new (object_path));
Packit Service c6b9b0
  interface = G_DBUS_INTERFACE_SKELETON (goa_identity_service_identity_skeleton_new ());
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_bind_property (identity, "identifier", interface, "identifier", G_BINDING_SYNC_CREATE);
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_bind_property (identity,
Packit Service c6b9b0
                          "expiration-timestamp",
Packit Service c6b9b0
                          interface,
Packit Service c6b9b0
                          "expiration-timestamp",
Packit Service c6b9b0
                          G_BINDING_SYNC_CREATE);
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_bind_property (identity, "is-signed-in", interface, "is-signed-in", G_BINDING_SYNC_CREATE);
Packit Service c6b9b0
Packit Service c6b9b0
  g_dbus_object_skeleton_add_interface (object, interface);
Packit Service c6b9b0
  g_object_unref (interface);
Packit Service c6b9b0
Packit Service c6b9b0
  g_dbus_object_manager_server_export (self->priv->object_manager_server, object);
Packit Service c6b9b0
  g_object_unref (object);
Packit Service c6b9b0
Packit Service c6b9b0
  return object_path;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
unexport_identity (GoaIdentityService *self,
Packit Service c6b9b0
                   GoaIdentity        *identity)
Packit Service c6b9b0
{
Packit Service c6b9b0
  char *object_path;
Packit Service c6b9b0
Packit Service c6b9b0
  object_path = get_object_path_for_identity (self, identity);
Packit Service c6b9b0
Packit Service c6b9b0
  g_dbus_object_manager_server_unexport (self->priv->object_manager_server,
Packit Service c6b9b0
                                         object_path);
Packit Service c6b9b0
  g_free (object_path);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_sign_in_done (GoaIdentityService *self,
Packit Service c6b9b0
                 GAsyncResult       *result,
Packit Service c6b9b0
                 GTask              *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentity      *identity;
Packit Service c6b9b0
  char             *object_path;
Packit Service c6b9b0
  GError           *error;
Packit Service c6b9b0
  gboolean          had_error;
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  /* Workaround for bgo#764163 */
Packit Service c6b9b0
  had_error = g_task_had_error (G_TASK (result));
Packit Service c6b9b0
  identity = g_task_propagate_pointer (G_TASK (result), &error);
Packit Service c6b9b0
  if (had_error)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_task_return_error (operation_result, error);
Packit Service c6b9b0
      g_object_unref (operation_result);
Packit Service c6b9b0
      return;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  object_path = export_identity (self, identity);
Packit Service c6b9b0
Packit Service c6b9b0
  g_task_return_pointer (operation_result, object_path, g_free);
Packit Service c6b9b0
Packit Service c6b9b0
  /* User is signed in, so we're mostly done
Packit Service c6b9b0
   */
Packit Service c6b9b0
  g_object_unref (identity);
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static GoaObject *
Packit Service c6b9b0
find_object_with_principal (GoaIdentityService *self,
Packit Service c6b9b0
                            const char         *principal,
Packit Service c6b9b0
                            gboolean            must_be_enabled)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GList      *objects;
Packit Service c6b9b0
  GList      *node;
Packit Service c6b9b0
  GoaObject  *found_object;
Packit Service c6b9b0
Packit Service c6b9b0
  objects = goa_client_get_accounts (self->priv->client);
Packit Service c6b9b0
Packit Service c6b9b0
  found_object = NULL;
Packit Service c6b9b0
  for (node = objects; node != NULL; node = node->next)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      GoaObject *object = GOA_OBJECT (node->data);
Packit Service c6b9b0
      GoaAccount *account;
Packit Service c6b9b0
      const char *provider_type;
Packit Service c6b9b0
      const char *account_identity;
Packit Service c6b9b0
Packit Service c6b9b0
      account = goa_object_peek_account (object);
Packit Service c6b9b0
Packit Service c6b9b0
      if (account == NULL)
Packit Service c6b9b0
        continue;
Packit Service c6b9b0
Packit Service c6b9b0
      provider_type = goa_account_get_provider_type (account);
Packit Service c6b9b0
Packit Service c6b9b0
      if (g_strcmp0 (provider_type, "kerberos") != 0)
Packit Service c6b9b0
        continue;
Packit Service c6b9b0
Packit Service c6b9b0
      if (must_be_enabled)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          GoaTicketing *ticketing;
Packit Service c6b9b0
Packit Service c6b9b0
          ticketing = goa_object_peek_ticketing (object);
Packit Service c6b9b0
Packit Service c6b9b0
          if (ticketing == NULL)
Packit Service c6b9b0
              continue;
Packit Service c6b9b0
        }
Packit Service c6b9b0
Packit Service c6b9b0
      account_identity = goa_account_get_identity (account);
Packit Service c6b9b0
Packit Service c6b9b0
      if (g_strcmp0 (account_identity, principal) == 0)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          found_object = g_object_ref (object);
Packit Service c6b9b0
          break;
Packit Service c6b9b0
        }
Packit Service c6b9b0
    }
Packit Service c6b9b0
  g_list_free_full (objects, g_object_unref);
Packit Service c6b9b0
Packit Service c6b9b0
  return found_object;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_credentials_ensured (GoaAccount         *account,
Packit Service c6b9b0
                        GAsyncResult       *result,
Packit Service c6b9b0
                        GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError     *error;
Packit Service c6b9b0
  const char *account_identity;
Packit Service c6b9b0
  int         expires_in;
Packit Service c6b9b0
Packit Service c6b9b0
  account_identity = goa_account_get_identity (account);
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  if (!goa_account_call_ensure_credentials_finish (account,
Packit Service c6b9b0
                                                   &expires_in,
Packit Service c6b9b0
                                                   result,
Packit Service c6b9b0
                                                   &error))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: could not ensure credentials for account %s: %s",
Packit Service c6b9b0
               account_identity,
Packit Service c6b9b0
               error->message);
Packit Service c6b9b0
      g_error_free (error);
Packit Service c6b9b0
      return;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: credentials for account %s ensured for %d seconds",
Packit Service c6b9b0
           account_identity,
Packit Service c6b9b0
           expires_in);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static gboolean
Packit Service c6b9b0
should_ignore_object (GoaIdentityService *self,
Packit Service c6b9b0
                      GoaObject          *object)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaAccount *account;
Packit Service c6b9b0
Packit Service c6b9b0
  account = goa_object_peek_account (object);
Packit Service c6b9b0
Packit Service c6b9b0
  if (goa_account_get_ticketing_disabled (account))
Packit Service c6b9b0
    return TRUE;
Packit Service c6b9b0
Packit Service c6b9b0
  return FALSE;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
ensure_account_credentials (GoaIdentityService *self,
Packit Service c6b9b0
                            GoaObject          *object)
Packit Service c6b9b0
{
Packit Service c6b9b0
Packit Service c6b9b0
  GoaAccount *account;
Packit Service c6b9b0
Packit Service c6b9b0
  if (should_ignore_object (self, object))
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  account = goa_object_peek_account (object);
Packit Service c6b9b0
  goa_account_call_ensure_credentials (account,
Packit Service c6b9b0
                                       NULL,
Packit Service c6b9b0
                                       (GAsyncReadyCallback)
Packit Service c6b9b0
                                       on_credentials_ensured,
Packit Service c6b9b0
                                       self);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_sign_in_handled (GoaIdentityService    *self,
Packit Service c6b9b0
                    GAsyncResult          *result,
Packit Service c6b9b0
                    GDBusMethodInvocation *invocation)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error = NULL;
Packit Service c6b9b0
  char *object_path;
Packit Service c6b9b0
Packit Service c6b9b0
  object_path = g_task_propagate_pointer (G_TASK (result), &error);
Packit Service c6b9b0
  if (error != NULL)
Packit Service c6b9b0
    g_dbus_method_invocation_take_error (invocation, error);
Packit Service c6b9b0
  else
Packit Service c6b9b0
    goa_identity_service_manager_complete_sign_in (GOA_IDENTITY_SERVICE_MANAGER (self),
Packit Service c6b9b0
                                                   invocation,
Packit Service c6b9b0
                                                   object_path);
Packit Service c6b9b0
Packit Service c6b9b0
  g_free (object_path);
Packit Service c6b9b0
  g_object_unref (invocation);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
read_sign_in_details (GoaIdentityServiceManager  *manager,
Packit Service c6b9b0
                      GVariant                   *details,
Packit Service c6b9b0
                      GoaIdentitySignInFlags     *flags,
Packit Service c6b9b0
                      char                      **secret_key,
Packit Service c6b9b0
                      char                      **preauth_source)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GVariantIter  iter;
Packit Service c6b9b0
  char          *key;
Packit Service c6b9b0
  char          *value;
Packit Service c6b9b0
Packit Service c6b9b0
  *flags = GOA_IDENTITY_SIGN_IN_FLAGS_NONE;
Packit Service c6b9b0
  g_variant_iter_init (&iter, details);
Packit Service c6b9b0
  while (g_variant_iter_loop (&iter, "{ss}", &key, &value))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (g_strcmp0 (key, "initial-password") == 0)
Packit Service c6b9b0
        *secret_key = g_strdup (value);
Packit Service c6b9b0
      else if (g_strcmp0 (key, "preauthentication-source") == 0)
Packit Service c6b9b0
        *preauth_source = g_strdup (value);
Packit Service c6b9b0
      else if (g_strcmp0 (key, "disallow-renewal") == 0
Packit Service c6b9b0
               && g_strcmp0 (value, "true") == 0)
Packit Service c6b9b0
        *flags |= GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_RENEWAL;
Packit Service c6b9b0
      else if (g_strcmp0 (key, "disallow-forwarding") == 0
Packit Service c6b9b0
               && g_strcmp0 (value, "true") == 0)
Packit Service c6b9b0
        *flags |= GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_FORWARDING;
Packit Service c6b9b0
      else if (g_strcmp0 (key, "disallow-proxying") == 0
Packit Service c6b9b0
               && g_strcmp0 (value, "true") == 0)
Packit Service c6b9b0
        *flags |= GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_PROXYING;
Packit Service c6b9b0
    }
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static gboolean
Packit Service c6b9b0
goa_identity_service_handle_sign_in (GoaIdentityServiceManager *manager,
Packit Service c6b9b0
                                     GDBusMethodInvocation     *invocation,
Packit Service c6b9b0
                                     const char                *identifier,
Packit Service c6b9b0
                                     GVariant                  *details)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService     *self = GOA_IDENTITY_SERVICE (manager);
Packit Service c6b9b0
  GTask                  *operation_result;
Packit Service c6b9b0
  GoaIdentitySignInFlags  flags;
Packit Service c6b9b0
  char                   *secret_key;
Packit Service c6b9b0
  char                   *preauth_source;
Packit Service c6b9b0
  gconstpointer           initial_password;
Packit Service c6b9b0
  GCancellable           *cancellable;
Packit Service c6b9b0
Packit Service c6b9b0
  secret_key = NULL;
Packit Service c6b9b0
  preauth_source = NULL;
Packit Service c6b9b0
  initial_password = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  read_sign_in_details (manager, details, &flags, &secret_key, &preauth_source);
Packit Service c6b9b0
Packit Service c6b9b0
  if (secret_key != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      GcrSecretExchange *secret_exchange;
Packit Service c6b9b0
      gchar *key;
Packit Service c6b9b0
Packit Service c6b9b0
      key = g_strdup_printf ("%s %s",
Packit Service c6b9b0
                             g_dbus_method_invocation_get_sender (invocation),
Packit Service c6b9b0
                             identifier);
Packit Service c6b9b0
Packit Service c6b9b0
      secret_exchange = g_hash_table_lookup (self->priv->key_holders, key);
Packit Service c6b9b0
      g_free (key);
Packit Service c6b9b0
Packit Service c6b9b0
      if (secret_exchange == NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          g_free (secret_key);
Packit Service c6b9b0
          g_dbus_method_invocation_return_error (invocation,
Packit Service c6b9b0
                                                 GOA_IDENTITY_MANAGER_ERROR,
Packit Service c6b9b0
                                                 GOA_IDENTITY_MANAGER_ERROR_ACCESSING_CREDENTIALS,
Packit Service c6b9b0
                                                 "initial secret passed before secret key exchange");
Packit Service c6b9b0
          return TRUE;
Packit Service c6b9b0
        }
Packit Service c6b9b0
Packit Service c6b9b0
      gcr_secret_exchange_receive (secret_exchange, secret_key);
Packit Service c6b9b0
      g_free (secret_key);
Packit Service c6b9b0
Packit Service c6b9b0
      initial_password = gcr_secret_exchange_get_secret (secret_exchange, NULL);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  cancellable = g_cancellable_new ();
Packit Service c6b9b0
  operation_result = g_task_new (self,
Packit Service c6b9b0
                                 cancellable,
Packit Service c6b9b0
                                 (GAsyncReadyCallback) on_sign_in_handled,
Packit Service c6b9b0
                                 g_object_ref (invocation));
Packit Service c6b9b0
  g_object_set_data (G_OBJECT (operation_result),
Packit Service c6b9b0
                     "initial-password",
Packit Service c6b9b0
                     (gpointer)
Packit Service c6b9b0
                     initial_password);
Packit Service c6b9b0
  g_object_set_data (G_OBJECT (operation_result),
Packit Service c6b9b0
                     "flags",
Packit Service c6b9b0
                     GINT_TO_POINTER ((int) flags));
Packit Service c6b9b0
Packit Service c6b9b0
  sign_in (self,
Packit Service c6b9b0
           identifier,
Packit Service c6b9b0
           initial_password,
Packit Service c6b9b0
           preauth_source,
Packit Service c6b9b0
           flags,
Packit Service c6b9b0
           cancellable,
Packit Service c6b9b0
           (GAsyncReadyCallback)
Packit Service c6b9b0
           on_sign_in_done,
Packit Service c6b9b0
           g_object_ref (operation_result));
Packit Service c6b9b0
Packit Service c6b9b0
  g_free (preauth_source);
Packit Service c6b9b0
  g_object_unref (cancellable);
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
Packit Service c6b9b0
  return TRUE;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_sign_out_handled (GoaIdentityService    *self,
Packit Service c6b9b0
                     GAsyncResult          *result,
Packit Service c6b9b0
                     GDBusMethodInvocation *invocation)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
  gboolean had_error;
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  /* Workaround for bgo#764163 */
Packit Service c6b9b0
  had_error = g_task_had_error (G_TASK (result));
Packit Service c6b9b0
  g_task_propagate_boolean (G_TASK (result), &error);
Packit Service c6b9b0
  if (had_error)
Packit Service c6b9b0
    g_dbus_method_invocation_take_error (invocation, error);
Packit Service c6b9b0
  else
Packit Service c6b9b0
    goa_identity_service_manager_complete_sign_out (GOA_IDENTITY_SERVICE_MANAGER (self),
Packit Service c6b9b0
                                                    invocation);
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_unref (invocation);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_signed_out (GoaIdentityManager *manager,
Packit Service c6b9b0
                        GAsyncResult       *result,
Packit Service c6b9b0
                        GTask              *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *self;
Packit Service c6b9b0
  GError             *error;
Packit Service c6b9b0
  GoaIdentity        *identity;
Packit Service c6b9b0
  const char         *identifier;
Packit Service c6b9b0
  GoaObject          *object = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  self = GOA_IDENTITY_SERVICE (g_task_get_source_object (operation_result));
Packit Service c6b9b0
  identity = g_object_get_data (G_OBJECT (operation_result), "identity");
Packit Service c6b9b0
Packit Service c6b9b0
  identifier = goa_identity_get_identifier (identity);
Packit Service c6b9b0
  object = find_object_with_principal (self, identifier, FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  if (object != NULL)
Packit Service c6b9b0
    ensure_account_credentials (self, object);
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  goa_identity_manager_sign_identity_out_finish (manager, result, &error);
Packit Service c6b9b0
  if (error != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: Identity could not be signed out: %s",
Packit Service c6b9b0
               error->message);
Packit Service c6b9b0
      g_task_return_error (operation_result, error);
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_task_return_boolean (operation_result, TRUE);
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_clear_object (&object);
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_got_identity_for_sign_out (GoaIdentityManager *manager,
Packit Service c6b9b0
                              GAsyncResult       *result,
Packit Service c6b9b0
                              GTask              *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
  GoaIdentity *identity = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  identity = goa_identity_manager_get_identity_finish (manager, result, &error);
Packit Service c6b9b0
Packit Service c6b9b0
  if (error != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: Identity could not be signed out: %s",
Packit Service c6b9b0
               error->message);
Packit Service c6b9b0
      g_task_return_error (operation_result, error);
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_set_data_full (G_OBJECT (operation_result), "identity", g_object_ref (identity), g_object_unref);
Packit Service c6b9b0
Packit Service c6b9b0
  goa_identity_manager_sign_identity_out (manager,
Packit Service c6b9b0
                                          identity,
Packit Service c6b9b0
                                          NULL,
Packit Service c6b9b0
                                          (GAsyncReadyCallback)
Packit Service c6b9b0
                                          on_identity_signed_out,
Packit Service c6b9b0
                                          g_object_ref (operation_result));
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_clear_object (&identity);
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static gboolean
Packit Service c6b9b0
goa_identity_service_handle_sign_out (GoaIdentityServiceManager *manager,
Packit Service c6b9b0
                                      GDBusMethodInvocation     *invocation,
Packit Service c6b9b0
                                      const char                *identifier)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *self = GOA_IDENTITY_SERVICE (manager);
Packit Service c6b9b0
  GTask *task;
Packit Service c6b9b0
Packit Service c6b9b0
  task = g_task_new (self, NULL, (GAsyncReadyCallback) on_sign_out_handled, g_object_ref (invocation));
Packit Service c6b9b0
  goa_identity_manager_get_identity (self->priv->identity_manager,
Packit Service c6b9b0
                                     identifier,
Packit Service c6b9b0
                                     NULL,
Packit Service c6b9b0
                                     (GAsyncReadyCallback)
Packit Service c6b9b0
                                     on_got_identity_for_sign_out,
Packit Service c6b9b0
                                     g_object_ref (task));
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_unref (task);
Packit Service c6b9b0
  return TRUE;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_secret_keys_exchanged (GoaIdentityService *self,
Packit Service c6b9b0
                          GAsyncResult       *result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GDBusMethodInvocation *invocation;
Packit Service c6b9b0
  GError                *error;
Packit Service c6b9b0
  char                  *output_key = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  invocation = g_task_get_task_data (G_TASK (result));
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  output_key = g_task_propagate_pointer (G_TASK (result), &error);
Packit Service c6b9b0
  if (error != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_dbus_method_invocation_take_error (invocation, error);
Packit Service c6b9b0
    }
Packit Service c6b9b0
  else
Packit Service c6b9b0
    {
Packit Service c6b9b0
      goa_identity_service_manager_complete_exchange_secret_keys (GOA_IDENTITY_SERVICE_MANAGER (self),
Packit Service c6b9b0
                                                                  invocation,
Packit Service c6b9b0
                                                                  output_key);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_free (output_key);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_caller_watched (GDBusConnection    *connection,
Packit Service c6b9b0
                   const char         *name,
Packit Service c6b9b0
                   const char         *name_owner,
Packit Service c6b9b0
                   GTask              *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService    *self;
Packit Service c6b9b0
  GcrSecretExchange     *secret_exchange;
Packit Service c6b9b0
  const char            *identifier;
Packit Service c6b9b0
  const char            *input_key;
Packit Service c6b9b0
  char                  *output_key;
Packit Service c6b9b0
Packit Service c6b9b0
  self = GOA_IDENTITY_SERVICE (g_task_get_source_object (operation_result));
Packit Service c6b9b0
  identifier = g_object_get_data (G_OBJECT (operation_result), "identifier");
Packit Service c6b9b0
  input_key = g_object_get_data (G_OBJECT (operation_result), "input-key");
Packit Service c6b9b0
Packit Service c6b9b0
  secret_exchange = gcr_secret_exchange_new (NULL);
Packit Service c6b9b0
Packit Service c6b9b0
  if (!gcr_secret_exchange_receive (secret_exchange,
Packit Service c6b9b0
                                    input_key))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_task_return_new_error (operation_result,
Packit Service c6b9b0
                               GCR_ERROR,
Packit Service c6b9b0
                               GCR_ERROR_UNRECOGNIZED,
Packit Service c6b9b0
                               _("Initial secret key is invalid"));
Packit Service c6b9b0
      return;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_hash_table_insert (self->priv->key_holders,
Packit Service c6b9b0
                       g_strdup_printf ("%s %s", name_owner, identifier),
Packit Service c6b9b0
                       secret_exchange);
Packit Service c6b9b0
Packit Service c6b9b0
  output_key = gcr_secret_exchange_send (secret_exchange, NULL, 0);
Packit Service c6b9b0
  g_task_return_pointer (operation_result, output_key, g_free);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_caller_vanished (GDBusConnection    *connection,
Packit Service c6b9b0
                    const char         *name,
Packit Service c6b9b0
                    GTask              *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *self;
Packit Service c6b9b0
  GCancellable       *cancellable;
Packit Service c6b9b0
Packit Service c6b9b0
  self = GOA_IDENTITY_SERVICE (g_task_get_source_object (operation_result));
Packit Service c6b9b0
Packit Service c6b9b0
  cancellable = g_task_get_cancellable (operation_result);
Packit Service c6b9b0
  g_cancellable_cancel (cancellable);
Packit Service c6b9b0
Packit Service c6b9b0
  g_hash_table_remove (self->priv->watched_client_connections, name);
Packit Service c6b9b0
  g_hash_table_remove (self->priv->key_holders, name);
Packit Service c6b9b0
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static gboolean
Packit Service c6b9b0
goa_identity_service_handle_exchange_secret_keys (GoaIdentityServiceManager *manager,
Packit Service c6b9b0
                                                  GDBusMethodInvocation     *invocation,
Packit Service c6b9b0
                                                  const char                *identifier,
Packit Service c6b9b0
                                                  const char                *input_key)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService     *self = GOA_IDENTITY_SERVICE (manager);
Packit Service c6b9b0
  GTask                  *operation_result;
Packit Service c6b9b0
  GCancellable           *cancellable;
Packit Service c6b9b0
  guint                   watch_id;
Packit Service c6b9b0
  const char             *sender;
Packit Service c6b9b0
Packit Service c6b9b0
  cancellable = g_cancellable_new ();
Packit Service c6b9b0
  operation_result = g_task_new (self, cancellable, (GAsyncReadyCallback) on_secret_keys_exchanged, NULL);
Packit Service c6b9b0
  g_task_set_task_data (operation_result, g_object_ref (invocation), g_object_unref);
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_set_data_full (G_OBJECT (operation_result),
Packit Service c6b9b0
                          "identifier",
Packit Service c6b9b0
                          g_strdup (identifier),
Packit Service c6b9b0
                          g_free);
Packit Service c6b9b0
  g_object_set_data_full (G_OBJECT (operation_result),
Packit Service c6b9b0
                          "input-key",
Packit Service c6b9b0
                          g_strdup (input_key),
Packit Service c6b9b0
                          g_free);
Packit Service c6b9b0
  sender = g_dbus_method_invocation_get_sender (invocation);
Packit Service c6b9b0
  watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
Packit Service c6b9b0
                               sender,
Packit Service c6b9b0
                               G_BUS_NAME_WATCHER_FLAGS_NONE,
Packit Service c6b9b0
                               (GBusNameAppearedCallback)
Packit Service c6b9b0
                               on_caller_watched,
Packit Service c6b9b0
                               (GBusNameVanishedCallback)
Packit Service c6b9b0
                               on_caller_vanished,
Packit Service c6b9b0
                               g_object_ref (operation_result),
Packit Service c6b9b0
                               g_object_unref);
Packit Service c6b9b0
  g_hash_table_insert (self->priv->watched_client_connections,
Packit Service c6b9b0
                       g_strdup (sender),
Packit Service c6b9b0
                       GUINT_TO_POINTER (watch_id));
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
  return TRUE;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
identity_service_manager_interface_init (GoaIdentityServiceManagerIface *interface)
Packit Service c6b9b0
{
Packit Service c6b9b0
  interface->handle_sign_in = goa_identity_service_handle_sign_in;
Packit Service c6b9b0
  interface->handle_sign_out = goa_identity_service_handle_sign_out;
Packit Service c6b9b0
  interface->handle_exchange_secret_keys = goa_identity_service_handle_exchange_secret_keys;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
goa_identity_service_init (GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
Packit Service c6b9b0
                                            GOA_TYPE_IDENTITY_SERVICE,
Packit Service c6b9b0
                                            GoaIdentityServicePrivate);
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: initializing");
Packit Service c6b9b0
  self->priv->watched_client_connections = g_hash_table_new_full (g_str_hash,
Packit Service c6b9b0
                                                                  g_str_equal,
Packit Service c6b9b0
                                                                  g_free,
Packit Service c6b9b0
                                                                  (GDestroyNotify)
Packit Service c6b9b0
                                                                  g_bus_unwatch_name);
Packit Service c6b9b0
Packit Service c6b9b0
  self->priv->key_holders = g_hash_table_new_full (g_str_hash,
Packit Service c6b9b0
                                                   g_str_equal,
Packit Service c6b9b0
                                                   g_free,
Packit Service c6b9b0
                                                   g_object_unref);
Packit Service c6b9b0
  self->priv->pending_temporary_account_results = g_hash_table_new_full (g_str_hash,
Packit Service c6b9b0
                                                                         g_str_equal,
Packit Service c6b9b0
                                                                         g_free,
Packit Service c6b9b0
                                                                         g_object_unref);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
goa_identity_service_finalize (GObject *object)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *self;
Packit Service c6b9b0
Packit Service c6b9b0
  g_return_if_fail (object != NULL);
Packit Service c6b9b0
  g_return_if_fail (GOA_IS_IDENTITY_SERVICE (object));
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: finalizing");
Packit Service c6b9b0
Packit Service c6b9b0
  self = GOA_IDENTITY_SERVICE (object);
Packit Service c6b9b0
Packit Service c6b9b0
  goa_identity_service_deactivate (self);
Packit Service c6b9b0
Packit Service c6b9b0
  g_clear_object (&self->priv->identity_manager);
Packit Service c6b9b0
  g_clear_object (&self->priv->object_manager_server);
Packit Service c6b9b0
  g_clear_pointer (&self->priv->watched_client_connections,
Packit Service c6b9b0
                   (GDestroyNotify) g_hash_table_unref);
Packit Service c6b9b0
  g_clear_pointer (&self->priv->key_holders,
Packit Service c6b9b0
                   (GDestroyNotify) g_hash_table_unref);
Packit Service c6b9b0
  g_clear_pointer (&self->priv->pending_temporary_account_results,
Packit Service c6b9b0
                   (GDestroyNotify) g_hash_table_unref);
Packit Service c6b9b0
Packit Service c6b9b0
  G_OBJECT_CLASS (goa_identity_service_parent_class)->finalize (object);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_renewed (GoaIdentityManager *manager,
Packit Service c6b9b0
                     GAsyncResult       *result,
Packit Service c6b9b0
                     GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  goa_identity_manager_renew_identity_finish (manager, result, &error);
Packit Service c6b9b0
Packit Service c6b9b0
  if (error != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: could not renew identity: %s",
Packit Service c6b9b0
               error->message);
Packit Service c6b9b0
      g_error_free (error);
Packit Service c6b9b0
      return;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: identity renewed");
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_needs_renewal (GoaIdentityManager *identity_manager,
Packit Service c6b9b0
                           GoaIdentity        *identity,
Packit Service c6b9b0
                           GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  const char *principal;
Packit Service c6b9b0
  GoaObject  *object = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  principal = goa_identity_get_identifier (identity);
Packit Service c6b9b0
Packit Service c6b9b0
  object = find_object_with_principal (self, principal, TRUE);
Packit Service c6b9b0
Packit Service c6b9b0
  if (object != NULL && should_ignore_object (self, object))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: ignoring identity %s that says it needs renewal", principal);
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: identity %s needs renewal", principal);
Packit Service c6b9b0
Packit Service c6b9b0
  goa_identity_manager_renew_identity (GOA_IDENTITY_MANAGER
Packit Service c6b9b0
                                       (self->priv->identity_manager),
Packit Service c6b9b0
                                       identity,
Packit Service c6b9b0
                                       NULL,
Packit Service c6b9b0
                                       (GAsyncReadyCallback)
Packit Service c6b9b0
                                       on_identity_renewed,
Packit Service c6b9b0
                                       self);
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_clear_object (&object);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_signed_in (GoaIdentityManager *manager,
Packit Service c6b9b0
                       GAsyncResult       *result,
Packit Service c6b9b0
                       GTask              *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
  GoaIdentity *identity;
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  identity = goa_identity_manager_sign_identity_in_finish (manager, result, &error);
Packit Service c6b9b0
Packit Service c6b9b0
  if (error != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: could not sign in identity: %s",
Packit Service c6b9b0
               error->message);
Packit Service c6b9b0
      g_task_return_error (operation_result, error);
Packit Service c6b9b0
    }
Packit Service c6b9b0
  else
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: identity signed in");
Packit Service c6b9b0
      g_task_return_pointer (operation_result, g_object_ref (identity), g_object_unref);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_temporary_account_added (GoaManager   *manager,
Packit Service c6b9b0
                            GAsyncResult *result,
Packit Service c6b9b0
                            GTask        *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *self;
Packit Service c6b9b0
  GDBusObjectManager *object_manager;
Packit Service c6b9b0
  const char *principal;
Packit Service c6b9b0
  char *object_path;
Packit Service c6b9b0
  GoaIdentity *identity;
Packit Service c6b9b0
  GoaObject *object;
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
Packit Service c6b9b0
  self = GOA_IDENTITY_SERVICE (g_task_get_source_object (operation_result));
Packit Service c6b9b0
  object_path = NULL;
Packit Service c6b9b0
  object = NULL;
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  identity = GOA_IDENTITY (g_task_get_task_data (operation_result));
Packit Service c6b9b0
Packit Service c6b9b0
  principal = goa_identity_get_identifier (identity);
Packit Service c6b9b0
  g_hash_table_remove (self->priv->pending_temporary_account_results, principal);
Packit Service c6b9b0
Packit Service c6b9b0
  if (!goa_manager_call_add_account_finish (manager,
Packit Service c6b9b0
                                            &object_path,
Packit Service c6b9b0
                                            result,
Packit Service c6b9b0
                                            &error))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      const char *identifier;
Packit Service c6b9b0
Packit Service c6b9b0
      identifier = goa_identity_get_identifier (identity);
Packit Service c6b9b0
      g_debug ("Could not add temporary account for identity %s: %s", identifier, error->message);
Packit Service c6b9b0
      g_error_free (error);
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  if (object_path != NULL && object_path[0] != '\0')
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("Created account for identity with object path %s", object_path);
Packit Service c6b9b0
Packit Service c6b9b0
      object_manager = goa_client_get_object_manager (self->priv->client);
Packit Service c6b9b0
      object = GOA_OBJECT (g_dbus_object_manager_get_object (object_manager,
Packit Service c6b9b0
                                                             object_path));
Packit Service c6b9b0
      g_free (object_path);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  if (object != NULL)
Packit Service c6b9b0
    ensure_account_credentials (self, object);
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_clear_object (&object);
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
add_temporary_account (GoaIdentityService *self,
Packit Service c6b9b0
                       GoaIdentity        *identity)
Packit Service c6b9b0
{
Packit Service c6b9b0
  char               *realm;
Packit Service c6b9b0
  char               *preauth_source;
Packit Service c6b9b0
  const char         *principal;
Packit Service c6b9b0
  GTask              *operation_result;
Packit Service c6b9b0
  GVariantBuilder     credentials;
Packit Service c6b9b0
  GVariantBuilder     details;
Packit Service c6b9b0
  GoaManager         *manager;
Packit Service c6b9b0
Packit Service c6b9b0
  principal = goa_identity_get_identifier (identity);
Packit Service c6b9b0
  if (g_hash_table_contains (self->priv->pending_temporary_account_results, principal))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: would add temporary identity %s, but it's already pending", principal);
Packit Service c6b9b0
      return;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: adding temporary identity %s", principal);
Packit Service c6b9b0
Packit Service c6b9b0
  /* If there's no account for this identity then create a temporary one.
Packit Service c6b9b0
   */
Packit Service c6b9b0
Packit Service c6b9b0
  realm = goa_kerberos_identity_get_realm_name (GOA_KERBEROS_IDENTITY (identity));
Packit Service c6b9b0
  preauth_source = goa_kerberos_identity_get_preauthentication_source (GOA_KERBEROS_IDENTITY (identity));
Packit Service c6b9b0
Packit Service c6b9b0
  g_variant_builder_init (&credentials, G_VARIANT_TYPE_VARDICT);
Packit Service c6b9b0
Packit Service c6b9b0
  g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
Packit Service c6b9b0
  g_variant_builder_add (&details, "{ss}", "Realm", realm);
Packit Service c6b9b0
  g_variant_builder_add (&details, "{ss}", "IsTemporary", "true");
Packit Service c6b9b0
  if (preauth_source != NULL)
Packit Service c6b9b0
    g_variant_builder_add (&details, "{ss}", "PreauthenticationSource", preauth_source);
Packit Service c6b9b0
  g_variant_builder_add (&details, "{ss}", "TicketingEnabled", "true");
Packit Service c6b9b0
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: asking to sign back in");
Packit Service c6b9b0
Packit Service c6b9b0
  operation_result = g_task_new (self, NULL, NULL, NULL);
Packit Service c6b9b0
  g_task_set_task_data (operation_result, g_object_ref (identity), g_object_unref);
Packit Service c6b9b0
Packit Service c6b9b0
  g_hash_table_insert (self->priv->pending_temporary_account_results,
Packit Service c6b9b0
                       g_strdup (principal),
Packit Service c6b9b0
                       g_object_ref (operation_result));
Packit Service c6b9b0
Packit Service c6b9b0
  manager = goa_client_get_manager (self->priv->client);
Packit Service c6b9b0
  goa_manager_call_add_account (manager,
Packit Service c6b9b0
                                "kerberos",
Packit Service c6b9b0
                                principal,
Packit Service c6b9b0
                                principal,
Packit Service c6b9b0
                                g_variant_builder_end (&credentials),
Packit Service c6b9b0
                                g_variant_builder_end (&details),
Packit Service c6b9b0
                                NULL,
Packit Service c6b9b0
                                (GAsyncReadyCallback)
Packit Service c6b9b0
                                on_temporary_account_added,
Packit Service c6b9b0
                                g_object_ref (operation_result));
Packit Service c6b9b0
  g_free (realm);
Packit Service c6b9b0
  g_free (preauth_source);
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_added (GoaIdentityManager *identity_manager,
Packit Service c6b9b0
                   GoaIdentity        *identity,
Packit Service c6b9b0
                   GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaObject *object;
Packit Service c6b9b0
  const char *identifier;
Packit Service c6b9b0
Packit Service c6b9b0
  export_identity (self, identity);
Packit Service c6b9b0
Packit Service c6b9b0
  identifier = goa_identity_get_identifier (identity);
Packit Service c6b9b0
Packit Service c6b9b0
  object = find_object_with_principal (self, identifier, FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  if (object == NULL)
Packit Service c6b9b0
    add_temporary_account (self, identity);
Packit Service c6b9b0
Packit Service c6b9b0
  g_clear_object (&object);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_removed (GoaIdentityManager *identity_manager,
Packit Service c6b9b0
                     GoaIdentity        *identity,
Packit Service c6b9b0
                     GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaObject *object;
Packit Service c6b9b0
  const char *identifier;
Packit Service c6b9b0
Packit Service c6b9b0
  identifier = goa_identity_get_identifier (identity);
Packit Service c6b9b0
  object = find_object_with_principal (self, identifier, FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  if (object != NULL)
Packit Service c6b9b0
    ensure_account_credentials (self, object);
Packit Service c6b9b0
Packit Service c6b9b0
  unexport_identity (self, identity);
Packit Service c6b9b0
  g_clear_object (&object);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_refreshed (GoaIdentityManager *identity_manager,
Packit Service c6b9b0
                       GoaIdentity        *identity,
Packit Service c6b9b0
                       GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaObject *object;
Packit Service c6b9b0
  const char *identifier;
Packit Service c6b9b0
Packit Service c6b9b0
  identifier = goa_identity_get_identifier (identity);
Packit Service c6b9b0
  object = find_object_with_principal (self, identifier, FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  if (object == NULL)
Packit Service c6b9b0
    add_temporary_account (self, identity);
Packit Service c6b9b0
  else
Packit Service c6b9b0
    ensure_account_credentials (self, object);
Packit Service c6b9b0
Packit Service c6b9b0
  g_clear_object (&object);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
typedef struct
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *service;
Packit Service c6b9b0
  GoaIdentity        *identity;
Packit Service c6b9b0
  GoaIdentityInquiry *inquiry;
Packit Service c6b9b0
  GoaIdentityQuery   *query;
Packit Service c6b9b0
  GcrSystemPrompt    *prompt;
Packit Service c6b9b0
  GCancellable       *cancellable;
Packit Service c6b9b0
} SystemPromptRequest;
Packit Service c6b9b0
Packit Service c6b9b0
static SystemPromptRequest *
Packit Service c6b9b0
system_prompt_request_new (GoaIdentityService *service,
Packit Service c6b9b0
                           GcrSystemPrompt    *prompt,
Packit Service c6b9b0
                           GoaIdentity        *identity,
Packit Service c6b9b0
                           GoaIdentityInquiry *inquiry,
Packit Service c6b9b0
                           GoaIdentityQuery   *query,
Packit Service c6b9b0
                           GCancellable       *cancellable)
Packit Service c6b9b0
{
Packit Service c6b9b0
  SystemPromptRequest *data;
Packit Service c6b9b0
Packit Service c6b9b0
  data = g_slice_new0 (SystemPromptRequest);
Packit Service c6b9b0
Packit Service c6b9b0
  data->service = service;
Packit Service c6b9b0
  data->prompt = prompt;
Packit Service c6b9b0
  data->identity = g_object_ref (identity);
Packit Service c6b9b0
  data->inquiry = g_object_ref (inquiry);
Packit Service c6b9b0
  data->query = query;
Packit Service c6b9b0
  data->cancellable = g_object_ref (cancellable);
Packit Service c6b9b0
Packit Service c6b9b0
  return data;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
system_prompt_request_free (SystemPromptRequest *data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  g_clear_object (&data->identity);
Packit Service c6b9b0
  g_clear_object (&data->inquiry);
Packit Service c6b9b0
  g_clear_object (&data->cancellable);
Packit Service c6b9b0
  g_slice_free (SystemPromptRequest, data);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
close_system_prompt (GoaIdentityManager  *manager,
Packit Service c6b9b0
                     GoaIdentity         *identity,
Packit Service c6b9b0
                     SystemPromptRequest *data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
Packit Service c6b9b0
  /* Only close the prompt if the identity we're
Packit Service c6b9b0
   * waiting on got refreshed
Packit Service c6b9b0
   */
Packit Service c6b9b0
  if (data->identity != identity)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  g_signal_handlers_disconnect_by_func (manager, G_CALLBACK (close_system_prompt), data);
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  if (!gcr_system_prompt_close (data->prompt, NULL, &error))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (error != NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          g_debug ("GoaIdentityService: could not close system prompt: %s",
Packit Service c6b9b0
                   error->message);
Packit Service c6b9b0
          g_error_free (error);
Packit Service c6b9b0
        }
Packit Service c6b9b0
    }
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_password_system_prompt_answered (GcrPrompt           *prompt,
Packit Service c6b9b0
                                    GAsyncResult        *result,
Packit Service c6b9b0
                                    SystemPromptRequest *request)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *self = request->service;
Packit Service c6b9b0
  GoaIdentityInquiry *inquiry = request->inquiry;
Packit Service c6b9b0
  GoaIdentity *identity = request->identity;
Packit Service c6b9b0
  GoaIdentityQuery *query = request->query;
Packit Service c6b9b0
  GCancellable *cancellable = request->cancellable;
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
  const char *password;
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  password = gcr_prompt_password_finish (prompt, result, &error);
Packit Service c6b9b0
Packit Service c6b9b0
  if (password == NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (error != NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          g_debug ("GoaIdentityService: could not get password from user: %s",
Packit Service c6b9b0
                   error->message);
Packit Service c6b9b0
          g_error_free (error);
Packit Service c6b9b0
        }
Packit Service c6b9b0
      else
Packit Service c6b9b0
        {
Packit Service c6b9b0
          g_cancellable_cancel (cancellable);
Packit Service c6b9b0
        }
Packit Service c6b9b0
    }
Packit Service c6b9b0
  else if (!g_cancellable_is_cancelled (cancellable))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      goa_identity_inquiry_answer_query (inquiry, query, password);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  close_system_prompt (self->priv->identity_manager, identity, request);
Packit Service c6b9b0
  system_prompt_request_free (request);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
query_user (GoaIdentityService *self,
Packit Service c6b9b0
            GoaIdentity        *identity,
Packit Service c6b9b0
            GoaIdentityInquiry *inquiry,
Packit Service c6b9b0
            GoaIdentityQuery   *query,
Packit Service c6b9b0
            GcrPrompt          *prompt,
Packit Service c6b9b0
            GCancellable       *cancellable)
Packit Service c6b9b0
{
Packit Service c6b9b0
  SystemPromptRequest *request;
Packit Service c6b9b0
  char *prompt_text;
Packit Service c6b9b0
  GoaIdentityQueryMode query_mode;
Packit Service c6b9b0
  char *description;
Packit Service c6b9b0
  char *name;
Packit Service c6b9b0
Packit Service c6b9b0
  g_assert (GOA_IS_KERBEROS_IDENTITY (identity));
Packit Service c6b9b0
Packit Service c6b9b0
  gcr_prompt_set_title (prompt, _("Log In to Realm"));
Packit Service c6b9b0
Packit Service c6b9b0
  name = goa_identity_manager_name_identity (self->priv->identity_manager, identity);
Packit Service c6b9b0
Packit Service c6b9b0
  description =
Packit Service c6b9b0
    g_strdup_printf (_("The network realm %s needs some information to sign you in."),
Packit Service c6b9b0
                     name);
Packit Service c6b9b0
  g_free (name);
Packit Service c6b9b0
Packit Service c6b9b0
  gcr_prompt_set_description (prompt, description);
Packit Service c6b9b0
  g_free (description);
Packit Service c6b9b0
Packit Service c6b9b0
  prompt_text = goa_identity_query_get_prompt (inquiry, query);
Packit Service c6b9b0
  gcr_prompt_set_message (prompt, prompt_text);
Packit Service c6b9b0
  g_free (prompt_text);
Packit Service c6b9b0
Packit Service c6b9b0
  request = system_prompt_request_new (self,
Packit Service c6b9b0
                                       GCR_SYSTEM_PROMPT (prompt),
Packit Service c6b9b0
                                       identity,
Packit Service c6b9b0
                                       inquiry,
Packit Service c6b9b0
                                       query,
Packit Service c6b9b0
                                       cancellable);
Packit Service c6b9b0
Packit Service c6b9b0
  g_signal_connect (self->priv->identity_manager,
Packit Service c6b9b0
                    "identity-refreshed",
Packit Service c6b9b0
                    G_CALLBACK (close_system_prompt),
Packit Service c6b9b0
                    request);
Packit Service c6b9b0
Packit Service c6b9b0
  query_mode = goa_identity_query_get_mode (inquiry, query);
Packit Service c6b9b0
Packit Service c6b9b0
  switch (query_mode)
Packit Service c6b9b0
    {
Packit Service c6b9b0
    case GOA_IDENTITY_QUERY_MODE_INVISIBLE:
Packit Service c6b9b0
      gcr_prompt_password_async (prompt,
Packit Service c6b9b0
                                 cancellable,
Packit Service c6b9b0
                                 (GAsyncReadyCallback)
Packit Service c6b9b0
                                 on_password_system_prompt_answered,
Packit Service c6b9b0
                                 request);
Packit Service c6b9b0
      break;
Packit Service c6b9b0
    case GOA_IDENTITY_QUERY_MODE_VISIBLE:
Packit Service c6b9b0
      /* FIXME: we need to either
Packit Service c6b9b0
       * 1) add new GCR api to allow for asking questions with visible answers
Packit Service c6b9b0
       * or
Packit Service c6b9b0
       * 2) add a new shell D-Bus api and drop GCR
Packit Service c6b9b0
       */
Packit Service c6b9b0
      gcr_prompt_password_async (prompt,
Packit Service c6b9b0
                                 cancellable,
Packit Service c6b9b0
                                 (GAsyncReadyCallback)
Packit Service c6b9b0
                                 on_password_system_prompt_answered,
Packit Service c6b9b0
                                 request);
Packit Service c6b9b0
      break;
Packit Service c6b9b0
    default:
Packit Service c6b9b0
      break;
Packit Service c6b9b0
    }
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
typedef struct
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *service;
Packit Service c6b9b0
  GoaIdentityInquiry *inquiry;
Packit Service c6b9b0
  GCancellable *cancellable;
Packit Service c6b9b0
} SystemPromptOpenRequest;
Packit Service c6b9b0
Packit Service c6b9b0
static SystemPromptOpenRequest *
Packit Service c6b9b0
system_prompt_open_request_new (GoaIdentityService *service,
Packit Service c6b9b0
                                GoaIdentityInquiry *inquiry,
Packit Service c6b9b0
                                GCancellable       *cancellable)
Packit Service c6b9b0
{
Packit Service c6b9b0
  SystemPromptOpenRequest *data;
Packit Service c6b9b0
Packit Service c6b9b0
  data = g_slice_new0 (SystemPromptOpenRequest);
Packit Service c6b9b0
Packit Service c6b9b0
  data->service = service;
Packit Service c6b9b0
  data->inquiry = g_object_ref (inquiry);
Packit Service c6b9b0
  data->cancellable = g_object_ref (cancellable);
Packit Service c6b9b0
Packit Service c6b9b0
  return data;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
system_prompt_open_request_free (SystemPromptOpenRequest *data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  g_clear_object (&data->inquiry);
Packit Service c6b9b0
  g_clear_object (&data->cancellable);
Packit Service c6b9b0
  g_slice_free (SystemPromptOpenRequest, data);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_system_prompt_open (GcrSystemPrompt         *system_prompt,
Packit Service c6b9b0
                       GAsyncResult            *result,
Packit Service c6b9b0
                       SystemPromptOpenRequest *request)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityService *self = request->service;
Packit Service c6b9b0
  GoaIdentityInquiry *inquiry = request->inquiry;
Packit Service c6b9b0
  GCancellable *cancellable = request->cancellable;
Packit Service c6b9b0
  GoaIdentity *identity;
Packit Service c6b9b0
  GoaIdentityQuery *query;
Packit Service c6b9b0
  GcrPrompt *prompt;
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
  GoaIdentityInquiryIter iter;
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  prompt = gcr_system_prompt_open_finish (result, &error);
Packit Service c6b9b0
Packit Service c6b9b0
  if (prompt == NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (error != NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          g_debug ("GoaIdentityService: could not open system prompt: %s",
Packit Service c6b9b0
                   error->message);
Packit Service c6b9b0
          g_error_free (error);
Packit Service c6b9b0
        }
Packit Service c6b9b0
      return;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  identity = goa_identity_inquiry_get_identity (inquiry);
Packit Service c6b9b0
  goa_identity_inquiry_iter_init (&iter, inquiry);
Packit Service c6b9b0
  while ((query = goa_identity_inquiry_iter_next (&iter, inquiry)) != NULL)
Packit Service c6b9b0
    query_user (self, identity, inquiry, query, prompt, cancellable);
Packit Service c6b9b0
Packit Service c6b9b0
  system_prompt_open_request_free (request);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_inquiry (GoaIdentityInquiry *inquiry,
Packit Service c6b9b0
                     GCancellable       *cancellable,
Packit Service c6b9b0
                     GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  SystemPromptOpenRequest *request;
Packit Service c6b9b0
Packit Service c6b9b0
  request = system_prompt_open_request_new (self, inquiry, cancellable);
Packit Service c6b9b0
  gcr_system_prompt_open_async (-1,
Packit Service c6b9b0
                                cancellable,
Packit Service c6b9b0
                                (GAsyncReadyCallback)
Packit Service c6b9b0
                                on_system_prompt_open,
Packit Service c6b9b0
                                request);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
cancel_sign_in (GoaIdentityManager *identity_manager,
Packit Service c6b9b0
                GoaIdentity        *identity,
Packit Service c6b9b0
                GTask              *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentity *operation_identity;
Packit Service c6b9b0
Packit Service c6b9b0
  operation_identity = g_task_get_task_data (operation_result);
Packit Service c6b9b0
  if (operation_identity == identity)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      GCancellable *cancellable;
Packit Service c6b9b0
Packit Service c6b9b0
      cancellable = g_task_get_cancellable (operation_result);
Packit Service c6b9b0
      g_cancellable_cancel (cancellable);
Packit Service c6b9b0
    }
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
sign_in (GoaIdentityService     *self,
Packit Service c6b9b0
         const char             *identifier,
Packit Service c6b9b0
         gconstpointer           initial_password,
Packit Service c6b9b0
         const char             *preauth_source,
Packit Service c6b9b0
         GoaIdentitySignInFlags  flags,
Packit Service c6b9b0
         GCancellable           *cancellable,
Packit Service c6b9b0
         GAsyncReadyCallback     callback,
Packit Service c6b9b0
         gpointer                user_data)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GTask *operation_result;
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: asking to sign in");
Packit Service c6b9b0
Packit Service c6b9b0
  operation_result = g_task_new (self, cancellable, callback, user_data);
Packit Service c6b9b0
  g_task_set_task_data (operation_result, user_data, NULL);
Packit Service c6b9b0
Packit Service c6b9b0
  g_signal_connect_object (self->priv->identity_manager,
Packit Service c6b9b0
                           "identity-refreshed",
Packit Service c6b9b0
                           G_CALLBACK (cancel_sign_in),
Packit Service c6b9b0
                           operation_result,
Packit Service c6b9b0
                           0);
Packit Service c6b9b0
Packit Service c6b9b0
  goa_identity_manager_sign_identity_in (self->priv->identity_manager,
Packit Service c6b9b0
                                         identifier,
Packit Service c6b9b0
                                         initial_password,
Packit Service c6b9b0
                                         preauth_source,
Packit Service c6b9b0
                                         flags,
Packit Service c6b9b0
                                         (GoaIdentityInquiryFunc)
Packit Service c6b9b0
                                         on_identity_inquiry,
Packit Service c6b9b0
                                         self,
Packit Service c6b9b0
                                         cancellable,
Packit Service c6b9b0
                                         (GAsyncReadyCallback)
Packit Service c6b9b0
                                         on_identity_signed_in,
Packit Service c6b9b0
                                         g_object_ref (operation_result));
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_expiring (GoaIdentityManager *identity_manager,
Packit Service c6b9b0
                      GoaIdentity        *identity,
Packit Service c6b9b0
                      GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  const char *principal;
Packit Service c6b9b0
  GoaObject  *object;
Packit Service c6b9b0
Packit Service c6b9b0
  principal = goa_identity_get_identifier (identity);
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: identity %s expiring", principal);
Packit Service c6b9b0
Packit Service c6b9b0
  object = find_object_with_principal (self, principal, TRUE);
Packit Service c6b9b0
Packit Service c6b9b0
  if (object == NULL)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  ensure_account_credentials (self, object);
Packit Service c6b9b0
  g_clear_object (&object);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identity_expired (GoaIdentityManager *identity_manager,
Packit Service c6b9b0
                     GoaIdentity        *identity,
Packit Service c6b9b0
                     GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  const char *principal;
Packit Service c6b9b0
  GoaObject  *object;
Packit Service c6b9b0
Packit Service c6b9b0
  principal = goa_identity_get_identifier (identity);
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: identity %s expired", principal);
Packit Service c6b9b0
Packit Service c6b9b0
  object = find_object_with_principal (self, principal, TRUE);
Packit Service c6b9b0
Packit Service c6b9b0
  if (object == NULL)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  ensure_account_credentials (self, object);
Packit Service c6b9b0
  g_clear_object (&object);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_sign_out_for_account_change_done (GoaIdentityService *self,
Packit Service c6b9b0
                                     GAsyncResult       *result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error = NULL;
Packit Service c6b9b0
  gboolean had_error;
Packit Service c6b9b0
Packit Service c6b9b0
  /* Workaround for bgo#764163 */
Packit Service c6b9b0
  had_error = g_task_had_error (G_TASK (result));
Packit Service c6b9b0
  g_task_propagate_boolean (G_TASK (result), &error);
Packit Service c6b9b0
  if (had_error)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("Log out failed: %s", error->message);
Packit Service c6b9b0
      g_error_free (error);
Packit Service c6b9b0
    }
Packit Service c6b9b0
  else
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("Log out complete");
Packit Service c6b9b0
    }
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_ticketing_done (GoaIdentityService *self,
Packit Service c6b9b0
                   GAsyncResult       *result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaObject *object;
Packit Service c6b9b0
Packit Service c6b9b0
  object = g_task_get_task_data (G_TASK (result));
Packit Service c6b9b0
  ensure_account_credentials (self, object);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_got_ticket (GoaTicketing *ticketing,
Packit Service c6b9b0
               GAsyncResult *result,
Packit Service c6b9b0
               GTask        *operation_result)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaObject          *object;
Packit Service c6b9b0
  GoaAccount         *account;
Packit Service c6b9b0
  GError             *error;
Packit Service c6b9b0
  const char         *account_identity;
Packit Service c6b9b0
Packit Service c6b9b0
  object = g_task_get_task_data (operation_result);
Packit Service c6b9b0
  account = goa_object_peek_account (object);
Packit Service c6b9b0
  account_identity = goa_account_get_identity (account);
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
  if (!goa_ticketing_call_get_ticket_finish (ticketing,
Packit Service c6b9b0
                                             result,
Packit Service c6b9b0
                                             &error))
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_debug ("GoaIdentityService: could not get ticket for account %s: %s",
Packit Service c6b9b0
               account_identity,
Packit Service c6b9b0
               error->message);
Packit Service c6b9b0
Packit Service c6b9b0
      g_task_return_error (operation_result, error);
Packit Service c6b9b0
      g_object_unref (operation_result);
Packit Service c6b9b0
      return;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: got ticket for account %s",
Packit Service c6b9b0
           account_identity);
Packit Service c6b9b0
  g_task_return_boolean (operation_result, TRUE);
Packit Service c6b9b0
  g_object_unref (operation_result);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_account_interface_added (GDBusObjectManager *manager,
Packit Service c6b9b0
                            GoaObject          *object,
Packit Service c6b9b0
                            GDBusInterface     *interface,
Packit Service c6b9b0
                            GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaAccount         *account;
Packit Service c6b9b0
  GoaTicketing       *ticketing;
Packit Service c6b9b0
  GDBusInterfaceInfo *info;
Packit Service c6b9b0
  const char         *provider_type;
Packit Service c6b9b0
Packit Service c6b9b0
  account = goa_object_peek_account (object);
Packit Service c6b9b0
Packit Service c6b9b0
  if (account == NULL)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  provider_type = goa_account_get_provider_type (account);
Packit Service c6b9b0
Packit Service c6b9b0
  if (g_strcmp0 (provider_type, "kerberos") != 0)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  info = g_dbus_interface_get_info (interface);
Packit Service c6b9b0
Packit Service c6b9b0
  if (g_strcmp0 (info->name, "org.gnome.OnlineAccounts.Ticketing") != 0)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  ticketing = goa_object_peek_ticketing (object);
Packit Service c6b9b0
Packit Service c6b9b0
  if (ticketing != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      GTask *operation_result;
Packit Service c6b9b0
Packit Service c6b9b0
      operation_result = g_task_new (self, NULL, (GAsyncReadyCallback) on_ticketing_done, NULL);
Packit Service c6b9b0
      g_task_set_task_data (operation_result, object, NULL);
Packit Service c6b9b0
Packit Service c6b9b0
      /* Ticketing interface is present, sign in if not already
Packit Service c6b9b0
       * signed in.
Packit Service c6b9b0
       */
Packit Service c6b9b0
      goa_ticketing_call_get_ticket (ticketing,
Packit Service c6b9b0
                                     NULL,
Packit Service c6b9b0
                                     (GAsyncReadyCallback)
Packit Service c6b9b0
                                     on_got_ticket,
Packit Service c6b9b0
                                     g_object_ref (operation_result));
Packit Service c6b9b0
Packit Service c6b9b0
      g_object_unref (operation_result);
Packit Service c6b9b0
      return;
Packit Service c6b9b0
    }
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_account_interface_removed (GDBusObjectManager *manager,
Packit Service c6b9b0
                              GoaObject          *object,
Packit Service c6b9b0
                              GDBusInterface     *interface,
Packit Service c6b9b0
                              GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaAccount         *account;
Packit Service c6b9b0
  GoaTicketing       *ticketing;
Packit Service c6b9b0
  GDBusInterfaceInfo *info;
Packit Service c6b9b0
  const char         *provider_type;
Packit Service c6b9b0
  const char         *account_identity;
Packit Service c6b9b0
  GTask              *task;
Packit Service c6b9b0
Packit Service c6b9b0
  account = goa_object_peek_account (object);
Packit Service c6b9b0
Packit Service c6b9b0
  if (account == NULL)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  provider_type = goa_account_get_provider_type (account);
Packit Service c6b9b0
Packit Service c6b9b0
  if (g_strcmp0 (provider_type, "kerberos") != 0)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  info = g_dbus_interface_get_info (interface);
Packit Service c6b9b0
Packit Service c6b9b0
  if (g_strcmp0 (info->name, "org.gnome.OnlineAccounts.Ticketing") != 0)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  ticketing = goa_object_peek_ticketing (object);
Packit Service c6b9b0
Packit Service c6b9b0
  if (ticketing != NULL)
Packit Service c6b9b0
    return;
Packit Service c6b9b0
Packit Service c6b9b0
  /* Ticketing interface is gone, sign out if not already
Packit Service c6b9b0
   * signed out. Also, since the user is playing around
Packit Service c6b9b0
   * with the account make it permanent.
Packit Service c6b9b0
   */
Packit Service c6b9b0
  goa_account_set_is_temporary (account, FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  account_identity = goa_account_get_identity (account);
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("Kerberos account %s was disabled and should now be signed out", account_identity);
Packit Service c6b9b0
Packit Service c6b9b0
  task = g_task_new (self, NULL, (GAsyncReadyCallback) on_sign_out_for_account_change_done, NULL);
Packit Service c6b9b0
  goa_identity_manager_get_identity (self->priv->identity_manager,
Packit Service c6b9b0
                                     account_identity,
Packit Service c6b9b0
                                     NULL,
Packit Service c6b9b0
                                     (GAsyncReadyCallback)
Packit Service c6b9b0
                                     on_got_identity_for_sign_out,
Packit Service c6b9b0
                                     g_object_ref (task));
Packit Service c6b9b0
Packit Service c6b9b0
  g_object_unref (task);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_identities_listed (GoaIdentityManager *manager,
Packit Service c6b9b0
                      GAsyncResult       *result,
Packit Service c6b9b0
                      GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error = NULL;
Packit Service c6b9b0
  GList *identities, *node;
Packit Service c6b9b0
Packit Service c6b9b0
  g_signal_connect (self->priv->identity_manager, "identity-added", G_CALLBACK (on_identity_added), self);
Packit Service c6b9b0
  g_signal_connect (self->priv->identity_manager, "identity-removed", G_CALLBACK (on_identity_removed), self);
Packit Service c6b9b0
  g_signal_connect (self->priv->identity_manager, "identity-refreshed", G_CALLBACK (on_identity_refreshed), self);
Packit Service c6b9b0
  g_signal_connect (self->priv->identity_manager,
Packit Service c6b9b0
                    "identity-needs-renewal",
Packit Service c6b9b0
                    G_CALLBACK (on_identity_needs_renewal),
Packit Service c6b9b0
                    self);
Packit Service c6b9b0
  g_signal_connect (self->priv->identity_manager, "identity-expiring", G_CALLBACK (on_identity_expiring), self);
Packit Service c6b9b0
  g_signal_connect (self->priv->identity_manager, "identity-expired", G_CALLBACK (on_identity_expired), self);
Packit Service c6b9b0
Packit Service c6b9b0
  identities = goa_identity_manager_list_identities_finish (manager, result, &error);
Packit Service c6b9b0
Packit Service c6b9b0
  if (identities == NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      if (error != NULL)
Packit Service c6b9b0
        {
Packit Service c6b9b0
          g_warning ("Could not list identities: %s", error->message);
Packit Service c6b9b0
          g_error_free (error);
Packit Service c6b9b0
        }
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  for (node = identities; node != NULL; node = node->next)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      GoaIdentity *identity = node->data;
Packit Service c6b9b0
      const char  *principal;
Packit Service c6b9b0
      GoaObject   *object;
Packit Service c6b9b0
      char        *object_path;
Packit Service c6b9b0
Packit Service c6b9b0
      object_path = export_identity (self, identity);
Packit Service c6b9b0
Packit Service c6b9b0
      principal = goa_identity_get_identifier (identity);
Packit Service c6b9b0
Packit Service c6b9b0
      object = find_object_with_principal (self, principal, TRUE);
Packit Service c6b9b0
Packit Service c6b9b0
      if (object == NULL)
Packit Service c6b9b0
        add_temporary_account (self, identity);
Packit Service c6b9b0
      else
Packit Service c6b9b0
        g_object_unref (object);
Packit Service c6b9b0
Packit Service c6b9b0
      g_free (object_path);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_object_unref (self);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
ensure_credentials_for_accounts (GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GDBusObjectManager *object_manager;
Packit Service c6b9b0
  GList      *accounts;
Packit Service c6b9b0
  GList      *node;
Packit Service c6b9b0
Packit Service c6b9b0
  object_manager = goa_client_get_object_manager (self->priv->client);
Packit Service c6b9b0
Packit Service c6b9b0
  g_signal_connect (object_manager, "interface-added", G_CALLBACK (on_account_interface_added), self);
Packit Service c6b9b0
  g_signal_connect (object_manager, "interface-removed", G_CALLBACK (on_account_interface_removed), self);
Packit Service c6b9b0
Packit Service c6b9b0
  accounts = goa_client_get_accounts (self->priv->client);
Packit Service c6b9b0
Packit Service c6b9b0
  for (node = accounts; node != NULL; node = node->next)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      GoaObject *object = GOA_OBJECT (node->data);
Packit Service c6b9b0
      GoaAccount *account;
Packit Service c6b9b0
      GoaTicketing *ticketing;
Packit Service c6b9b0
      const char *provider_type;
Packit Service c6b9b0
Packit Service c6b9b0
      account = goa_object_peek_account (object);
Packit Service c6b9b0
Packit Service c6b9b0
      if (account == NULL)
Packit Service c6b9b0
        continue;
Packit Service c6b9b0
Packit Service c6b9b0
      provider_type = goa_account_get_provider_type (account);
Packit Service c6b9b0
Packit Service c6b9b0
      if (g_strcmp0 (provider_type, "kerberos") != 0)
Packit Service c6b9b0
        continue;
Packit Service c6b9b0
Packit Service c6b9b0
      ticketing = goa_object_peek_ticketing (object);
Packit Service c6b9b0
Packit Service c6b9b0
      if (ticketing == NULL)
Packit Service c6b9b0
        continue;
Packit Service c6b9b0
Packit Service c6b9b0
      ensure_account_credentials (self, object);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_list_free_full (accounts, g_object_unref);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_got_client (GoaClient          *client,
Packit Service c6b9b0
               GAsyncResult       *result,
Packit Service c6b9b0
               GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GError *error;
Packit Service c6b9b0
Packit Service c6b9b0
  error = NULL;
Packit Service c6b9b0
Packit Service c6b9b0
  self->priv->client = goa_client_new_finish (result, &error);
Packit Service c6b9b0
Packit Service c6b9b0
  if (self->priv->client == NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_warning ("Could not create client: %s", error->message);
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  self->priv->identity_manager = goa_kerberos_identity_manager_new (NULL, &error);
Packit Service c6b9b0
Packit Service c6b9b0
  if (self->priv->identity_manager == NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_warning ("Could not create identity manager: %s", error->message);
Packit Service c6b9b0
      goto out;
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  goa_identity_manager_list_identities (self->priv->identity_manager,
Packit Service c6b9b0
                                        NULL,
Packit Service c6b9b0
                                        (GAsyncReadyCallback)
Packit Service c6b9b0
                                        on_identities_listed,
Packit Service c6b9b0
                                        g_object_ref (self));
Packit Service c6b9b0
Packit Service c6b9b0
  ensure_credentials_for_accounts (self);
Packit Service c6b9b0
Packit Service c6b9b0
 out:
Packit Service c6b9b0
  g_object_unref (self);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_session_bus_acquired (GDBusConnection    *connection,
Packit Service c6b9b0
                         const char         *unique_name,
Packit Service c6b9b0
                         GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  g_debug ("GoaIdentityService: Connected to session bus");
Packit Service c6b9b0
Packit Service c6b9b0
  if (self->priv->connection == NULL)
Packit Service c6b9b0
  {
Packit Service c6b9b0
    self->priv->connection = g_object_ref (connection);
Packit Service c6b9b0
Packit Service c6b9b0
    g_dbus_object_manager_server_set_connection (self->priv->object_manager_server,
Packit Service c6b9b0
                                                 self->priv->connection);
Packit Service c6b9b0
Packit Service c6b9b0
    goa_client_new (NULL,
Packit Service c6b9b0
                    (GAsyncReadyCallback)
Packit Service c6b9b0
                    on_got_client,
Packit Service c6b9b0
                    g_object_ref (self));
Packit Service c6b9b0
  }
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_name_acquired (GDBusConnection    *connection,
Packit Service c6b9b0
                  const char         *name,
Packit Service c6b9b0
                  GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  if (g_strcmp0 (name, "org.gnome.Identity") == 0)
Packit Service c6b9b0
    g_debug ("GoaIdentityService: Acquired name org.gnome.Identity");
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
on_name_lost (GDBusConnection    *connection,
Packit Service c6b9b0
              const char         *name,
Packit Service c6b9b0
              GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  if (g_strcmp0 (name, "org.gnome.Identity") == 0)
Packit Service c6b9b0
    raise (SIGTERM);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
gboolean
Packit Service c6b9b0
goa_identity_service_activate (GoaIdentityService   *self,
Packit Service c6b9b0
                               GError              **error)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GoaIdentityServiceObjectSkeleton *object;
Packit Service c6b9b0
Packit Service c6b9b0
  g_return_val_if_fail (GOA_IS_IDENTITY_SERVICE (self), FALSE);
Packit Service c6b9b0
Packit Service c6b9b0
  g_debug ("GoaIdentityService: Activating identity service");
Packit Service c6b9b0
Packit Service c6b9b0
  self->priv->object_manager_server =
Packit Service c6b9b0
    g_dbus_object_manager_server_new ("/org/gnome/Identity");
Packit Service c6b9b0
Packit Service c6b9b0
  object = goa_identity_service_object_skeleton_new ("/org/gnome/Identity/Manager");
Packit Service c6b9b0
  goa_identity_service_object_skeleton_set_manager (object,
Packit Service c6b9b0
                                                    GOA_IDENTITY_SERVICE_MANAGER (self));
Packit Service c6b9b0
Packit Service c6b9b0
  g_dbus_object_manager_server_export (self->priv->object_manager_server,
Packit Service c6b9b0
                                       G_DBUS_OBJECT_SKELETON (object));
Packit Service c6b9b0
  g_object_unref (object);
Packit Service c6b9b0
Packit Service c6b9b0
  self->priv->bus_id = g_bus_own_name (G_BUS_TYPE_SESSION,
Packit Service c6b9b0
                                       "org.gnome.Identity",
Packit Service c6b9b0
                                       G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
Packit Service c6b9b0
                                       G_BUS_NAME_OWNER_FLAGS_REPLACE,
Packit Service c6b9b0
                                       (GBusAcquiredCallback) on_session_bus_acquired,
Packit Service c6b9b0
                                       (GBusNameAcquiredCallback) on_name_acquired,
Packit Service c6b9b0
                                       (GBusNameVanishedCallback) on_name_lost,
Packit Service c6b9b0
                                       self,
Packit Service c6b9b0
                                       NULL);
Packit Service c6b9b0
Packit Service c6b9b0
  return TRUE;
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
void
Packit Service c6b9b0
goa_identity_service_deactivate (GoaIdentityService *self)
Packit Service c6b9b0
{
Packit Service c6b9b0
  g_debug ("GoaIdentityService: Deactivating identity service");
Packit Service c6b9b0
Packit Service c6b9b0
  if (self->priv->identity_manager != NULL)
Packit Service c6b9b0
    {
Packit Service c6b9b0
      g_signal_handlers_disconnect_by_func (self, on_identity_needs_renewal, self);
Packit Service c6b9b0
      g_signal_handlers_disconnect_by_func (self, on_identity_expiring, self);
Packit Service c6b9b0
      g_signal_handlers_disconnect_by_func (self, on_identity_expired, self);
Packit Service c6b9b0
      g_clear_object (&self->priv->identity_manager);
Packit Service c6b9b0
    }
Packit Service c6b9b0
Packit Service c6b9b0
  g_clear_object (&self->priv->object_manager_server);
Packit Service c6b9b0
  g_clear_object (&self->priv->connection);
Packit Service c6b9b0
  g_clear_object (&self->priv->client);
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
static void
Packit Service c6b9b0
goa_identity_service_class_init (GoaIdentityServiceClass *service_class)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GObjectClass *object_class = G_OBJECT_CLASS (service_class);
Packit Service c6b9b0
Packit Service c6b9b0
  object_class->finalize = goa_identity_service_finalize;
Packit Service c6b9b0
Packit Service c6b9b0
  goa_identity_utils_register_error_domain (GOA_IDENTITY_ERROR, GOA_TYPE_IDENTITY_ERROR);
Packit Service c6b9b0
  goa_identity_utils_register_error_domain (GOA_IDENTITY_MANAGER_ERROR, GOA_TYPE_IDENTITY_MANAGER_ERROR);
Packit Service c6b9b0
Packit Service c6b9b0
  g_type_class_add_private (service_class, sizeof (GoaIdentityServicePrivate));
Packit Service c6b9b0
}
Packit Service c6b9b0
Packit Service c6b9b0
GoaIdentityService *
Packit Service c6b9b0
goa_identity_service_new (void)
Packit Service c6b9b0
{
Packit Service c6b9b0
  GObject *object;
Packit Service c6b9b0
Packit Service c6b9b0
  object = g_object_new (GOA_TYPE_IDENTITY_SERVICE,
Packit Service c6b9b0
                         NULL);
Packit Service c6b9b0
Packit Service c6b9b0
  return GOA_IDENTITY_SERVICE (object);
Packit Service c6b9b0
}