Blame src/goaidentity/goakerberosidentity.c

Packit 79f644
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
Packit 79f644
/*
Packit 79f644
 * Copyright © 2012 – 2017 Red Hat, Inc.
Packit 79f644
 *
Packit 79f644
 * This library is free software; you can redistribute it and/or
Packit 79f644
 * modify it under the terms of the GNU Lesser General Public
Packit 79f644
 * License as published by the Free Software Foundation; either
Packit 79f644
 * version 2 of the License, or (at your option) any later version.
Packit 79f644
 *
Packit 79f644
 * This library is distributed in the hope that it will be useful,
Packit 79f644
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 79f644
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 79f644
 * Lesser General Public License for more details.
Packit 79f644
 *
Packit 79f644
 * You should have received a copy of the GNU Lesser General
Packit 79f644
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit 79f644
 */
Packit 79f644
Packit 79f644
#include "config.h"
Packit 79f644
Packit 79f644
#include "goaidentity.h"
Packit 79f644
#include "goakerberosidentity.h"
Packit 79f644
#include "goakerberosidentityinquiry.h"
Packit 79f644
#include "goaalarm.h"
Packit 79f644
Packit 79f644
#include <netinet/in.h>
Packit 79f644
#include <arpa/nameser.h>
Packit 79f644
#include <resolv.h>
Packit 79f644
Packit 79f644
#include <string.h>
Packit 79f644
#include <glib/gi18n.h>
Packit 79f644
#include <gio/gio.h>
Packit 79f644
Packit 79f644
typedef enum
Packit 79f644
{
Packit 79f644
  VERIFICATION_LEVEL_UNVERIFIED,
Packit 79f644
  VERIFICATION_LEVEL_ERROR,
Packit 79f644
  VERIFICATION_LEVEL_EXISTS,
Packit 79f644
  VERIFICATION_LEVEL_SIGNED_IN
Packit 79f644
} VerificationLevel;
Packit 79f644
Packit 79f644
struct _GoaKerberosIdentityPrivate
Packit 79f644
{
Packit 79f644
  krb5_context kerberos_context;
Packit 79f644
  krb5_ccache  credentials_cache;
Packit 79f644
Packit 79f644
  char *identifier;
Packit 79f644
  guint identifier_idle_id;
Packit 79f644
Packit 79f644
  char *preauth_identity_source;
Packit 79f644
Packit 79f644
  krb5_timestamp start_time;
Packit 79f644
  guint          start_time_idle_id;
Packit 79f644
  krb5_timestamp renewal_time;
Packit 79f644
  guint          renewal_time_idle_id;
Packit 79f644
  krb5_timestamp expiration_time;
Packit 79f644
  guint          expiration_time_idle_id;
Packit 79f644
Packit 79f644
  GoaAlarm     *expiration_alarm;
Packit 79f644
  GoaAlarm     *expiring_alarm;
Packit 79f644
  GoaAlarm     *renewal_alarm;
Packit 79f644
Packit 79f644
  VerificationLevel cached_verification_level;
Packit 79f644
  guint             is_signed_in_idle_id;
Packit 79f644
};
Packit 79f644
Packit 79f644
enum
Packit 79f644
{
Packit 79f644
  EXPIRING,
Packit 79f644
  EXPIRED,
Packit 79f644
  UNEXPIRED,
Packit 79f644
  NEEDS_RENEWAL,
Packit 79f644
  NEEDS_REFRESH,
Packit 79f644
  NUMBER_OF_SIGNALS,
Packit 79f644
};
Packit 79f644
Packit 79f644
enum
Packit 79f644
{
Packit 79f644
  PROP_0,
Packit 79f644
  PROP_IDENTIFIER,
Packit 79f644
  PROP_IS_SIGNED_IN,
Packit 79f644
  PROP_START_TIMESTAMP,
Packit 79f644
  PROP_RENEWAL_TIMESTAMP,
Packit 79f644
  PROP_EXPIRATION_TIMESTAMP
Packit 79f644
};
Packit 79f644
Packit 79f644
static guint signals[NUMBER_OF_SIGNALS] = { 0 };
Packit 79f644
Packit 79f644
static void identity_interface_init (GoaIdentityInterface *interface);
Packit 79f644
static void initable_interface_init (GInitableIface *interface);
Packit 79f644
static void reset_alarms (GoaKerberosIdentity *self);
Packit 79f644
static void clear_alarms (GoaKerberosIdentity *self);
Packit 79f644
static gboolean goa_kerberos_identity_is_signed_in (GoaIdentity *identity);
Packit 79f644
static void set_and_prefix_error_from_krb5_error_code (GoaKerberosIdentity  *self,
Packit 79f644
                                                       GError              **error,
Packit 79f644
                                                       gint                  code,
Packit 79f644
                                                       krb5_error_code       error_code,
Packit 79f644
                                                       const char           *format,
Packit 79f644
                                                       ...) G_GNUC_PRINTF (5, 6);
Packit 79f644
Packit 79f644
G_LOCK_DEFINE_STATIC (identity_lock);
Packit 79f644
Packit 79f644
G_DEFINE_TYPE_WITH_CODE (GoaKerberosIdentity,
Packit 79f644
                         goa_kerberos_identity,
Packit 79f644
                         G_TYPE_OBJECT,
Packit 79f644
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
Packit 79f644
                                                initable_interface_init)
Packit 79f644
                         G_IMPLEMENT_INTERFACE (GOA_TYPE_IDENTITY,
Packit 79f644
                                                identity_interface_init));
Packit 79f644
static void
Packit 79f644
goa_kerberos_identity_dispose (GObject *object)
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity *self = GOA_KERBEROS_IDENTITY (object);
Packit 79f644
Packit 79f644
  G_LOCK (identity_lock);
Packit 79f644
  clear_alarms (self);
Packit 79f644
  g_clear_pointer (&self->priv->preauth_identity_source,
Packit 79f644
                   g_free);
Packit 79f644
  G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
  G_OBJECT_CLASS (goa_kerberos_identity_parent_class)->dispose (object);
Packit 79f644
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_kerberos_identity_finalize (GObject *object)
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity *self = GOA_KERBEROS_IDENTITY (object);
Packit 79f644
Packit 79f644
  g_free (self->priv->identifier);
Packit 79f644
Packit 79f644
  if (self->priv->credentials_cache != NULL)
Packit 79f644
    krb5_cc_close (self->priv->kerberos_context, self->priv->credentials_cache);
Packit 79f644
Packit 79f644
  G_OBJECT_CLASS (goa_kerberos_identity_parent_class)->finalize (object);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_kerberos_identity_get_property (GObject    *object,
Packit 79f644
                                    guint       property_id,
Packit 79f644
                                    GValue     *value,
Packit 79f644
                                    GParamSpec *param_spec)
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity *self = GOA_KERBEROS_IDENTITY (object);
Packit 79f644
Packit 79f644
  switch (property_id)
Packit 79f644
    {
Packit 79f644
    case PROP_IDENTIFIER:
Packit 79f644
      G_LOCK (identity_lock);
Packit 79f644
      g_value_set_string (value, self->priv->identifier);
Packit 79f644
      G_UNLOCK (identity_lock);
Packit 79f644
      break;
Packit 79f644
    case PROP_IS_SIGNED_IN:
Packit 79f644
      g_value_set_boolean (value,
Packit 79f644
                           goa_kerberos_identity_is_signed_in (GOA_IDENTITY (self)));
Packit 79f644
      break;
Packit 79f644
    case PROP_START_TIMESTAMP:
Packit 79f644
      G_LOCK (identity_lock);
Packit 79f644
      g_value_set_int64 (value, (gint64) self->priv->start_time);
Packit 79f644
      G_UNLOCK (identity_lock);
Packit 79f644
      break;
Packit 79f644
    case PROP_RENEWAL_TIMESTAMP:
Packit 79f644
      G_LOCK (identity_lock);
Packit 79f644
      g_value_set_int64 (value, (gint64) self->priv->renewal_time);
Packit 79f644
      G_UNLOCK (identity_lock);
Packit 79f644
      break;
Packit 79f644
    case PROP_EXPIRATION_TIMESTAMP:
Packit 79f644
      G_LOCK (identity_lock);
Packit 79f644
      g_value_set_int64 (value, (gint64) self->priv->expiration_time);
Packit 79f644
      G_UNLOCK (identity_lock);
Packit 79f644
      break;
Packit 79f644
    default:
Packit 79f644
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, param_spec);
Packit 79f644
      break;
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_kerberos_identity_class_init (GoaKerberosIdentityClass *klass)
Packit 79f644
{
Packit 79f644
  GObjectClass *object_class;
Packit 79f644
Packit 79f644
  object_class = G_OBJECT_CLASS (klass);
Packit 79f644
Packit 79f644
  object_class->dispose = goa_kerberos_identity_dispose;
Packit 79f644
  object_class->finalize = goa_kerberos_identity_finalize;
Packit 79f644
  object_class->get_property = goa_kerberos_identity_get_property;
Packit 79f644
Packit 79f644
  g_type_class_add_private (klass, sizeof (GoaKerberosIdentityPrivate));
Packit 79f644
Packit 79f644
  signals[EXPIRING] = g_signal_new ("expiring",
Packit 79f644
                                    G_TYPE_FROM_CLASS (klass),
Packit 79f644
                                    G_SIGNAL_RUN_LAST,
Packit 79f644
                                    0,
Packit 79f644
                                    NULL,
Packit 79f644
                                    NULL,
Packit 79f644
                                    NULL,
Packit 79f644
                                    G_TYPE_NONE,
Packit 79f644
                                    0);
Packit 79f644
  signals[EXPIRED] = g_signal_new ("expired",
Packit 79f644
                                   G_TYPE_FROM_CLASS (klass),
Packit 79f644
                                   G_SIGNAL_RUN_LAST,
Packit 79f644
                                   0,
Packit 79f644
                                   NULL,
Packit 79f644
                                   NULL,
Packit 79f644
                                   NULL,
Packit 79f644
                                   G_TYPE_NONE,
Packit 79f644
                                   0);
Packit 79f644
  signals[UNEXPIRED] = g_signal_new ("unexpired",
Packit 79f644
                                     G_TYPE_FROM_CLASS (klass),
Packit 79f644
                                     G_SIGNAL_RUN_LAST,
Packit 79f644
                                     0,
Packit 79f644
                                     NULL,
Packit 79f644
                                     NULL,
Packit 79f644
                                     NULL,
Packit 79f644
                                     G_TYPE_NONE,
Packit 79f644
                                     0);
Packit 79f644
  signals[NEEDS_RENEWAL] = g_signal_new ("needs-renewal",
Packit 79f644
                                         G_TYPE_FROM_CLASS (klass),
Packit 79f644
                                         G_SIGNAL_RUN_LAST,
Packit 79f644
                                         0,
Packit 79f644
                                         NULL,
Packit 79f644
                                         NULL,
Packit 79f644
                                         NULL,
Packit 79f644
                                         G_TYPE_NONE,
Packit 79f644
                                         0);
Packit 79f644
  signals[NEEDS_REFRESH] = g_signal_new ("needs-refresh",
Packit 79f644
                                         G_TYPE_FROM_CLASS (klass),
Packit 79f644
                                         G_SIGNAL_RUN_LAST,
Packit 79f644
                                         0,
Packit 79f644
                                         NULL,
Packit 79f644
                                         NULL,
Packit 79f644
                                         NULL,
Packit 79f644
                                         G_TYPE_NONE,
Packit 79f644
                                         0);
Packit 79f644
Packit 79f644
  g_object_class_override_property (object_class, PROP_IDENTIFIER, "identifier");
Packit 79f644
  g_object_class_override_property (object_class, PROP_IS_SIGNED_IN, "is-signed-in");
Packit 79f644
  g_object_class_override_property (object_class,
Packit 79f644
                                    PROP_START_TIMESTAMP,
Packit 79f644
                                    "start-timestamp");
Packit 79f644
  g_object_class_override_property (object_class,
Packit 79f644
                                    PROP_RENEWAL_TIMESTAMP,
Packit 79f644
                                    "renewal-timestamp");
Packit 79f644
  g_object_class_override_property (object_class,
Packit 79f644
                                    PROP_EXPIRATION_TIMESTAMP,
Packit 79f644
                                    "expiration-timestamp");
Packit 79f644
Packit 79f644
}
Packit 79f644
Packit 79f644
static char *
Packit 79f644
get_identifier (GoaKerberosIdentity  *self,
Packit 79f644
                GError              **error)
Packit 79f644
{
Packit 79f644
  krb5_principal principal;
Packit 79f644
  krb5_error_code error_code;
Packit 79f644
  char *unparsed_name;
Packit 79f644
  char *identifier = NULL;
Packit 79f644
Packit 79f644
  if (self->priv->credentials_cache == NULL)
Packit 79f644
    return NULL;
Packit 79f644
Packit 79f644
  error_code = krb5_cc_get_principal (self->priv->kerberos_context,
Packit 79f644
                                      self->priv->credentials_cache,
Packit 79f644
                                      &principal);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      if (error_code == KRB5_CC_END)
Packit 79f644
        {
Packit 79f644
          set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                     error,
Packit 79f644
                                                     GOA_IDENTITY_ERROR_CREDENTIALS_UNAVAILABLE,
Packit 79f644
                                                     error_code,
Packit 79f644
                                                     _("Could not find identity in credential cache: "));
Packit 79f644
        }
Packit 79f644
      else
Packit 79f644
        {
Packit 79f644
          set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                     error,
Packit 79f644
                                                     GOA_IDENTITY_ERROR_ENUMERATING_CREDENTIALS,
Packit 79f644
                                                     error_code,
Packit 79f644
                                                     _("Could not find identity in credential cache: "));
Packit 79f644
        }
Packit 79f644
      return NULL;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  error_code = krb5_unparse_name_flags (self->priv->kerberos_context,
Packit 79f644
                                        principal,
Packit 79f644
                                        0,
Packit 79f644
                                        &unparsed_name);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      const char *error_message;
Packit 79f644
Packit 79f644
      error_message =
Packit 79f644
        krb5_get_error_message (self->priv->kerberos_context, error_code);
Packit 79f644
      g_debug ("GoaKerberosIdentity: Error parsing principal identity name: %s",
Packit 79f644
               error_message);
Packit 79f644
      krb5_free_error_message (self->priv->kerberos_context, error_message);
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  identifier = g_strdup (unparsed_name);
Packit 79f644
  krb5_free_unparsed_name (self->priv->kerberos_context, unparsed_name);
Packit 79f644
Packit 79f644
out:
Packit 79f644
  krb5_free_principal (self->priv->kerberos_context, principal);
Packit 79f644
  return identifier;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_kerberos_identity_init (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
Packit 79f644
                                            GOA_TYPE_KERBEROS_IDENTITY,
Packit 79f644
                                            GoaKerberosIdentityPrivate);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
set_and_prefix_error_from_krb5_error_code (GoaKerberosIdentity  *self,
Packit 79f644
                                           GError              **error,
Packit 79f644
                                           gint                  code,
Packit 79f644
                                           krb5_error_code       error_code,
Packit 79f644
                                           const char           *format,
Packit 79f644
                                           ...)
Packit 79f644
{
Packit 79f644
  const char *error_message;
Packit 79f644
  char *literal_prefix;
Packit 79f644
  va_list args;
Packit 79f644
Packit 79f644
  error_message = krb5_get_error_message (self->priv->kerberos_context, error_code);
Packit 79f644
  g_set_error_literal (error, GOA_IDENTITY_ERROR, code, error_message);
Packit 79f644
Packit 79f644
  va_start (args, format);
Packit 79f644
  literal_prefix = g_strdup_vprintf (format, args);
Packit 79f644
  va_end (args);
Packit 79f644
Packit 79f644
  g_prefix_error (error, "%s", literal_prefix);
Packit 79f644
Packit 79f644
  g_free (literal_prefix);
Packit 79f644
  krb5_free_error_message (self->priv->kerberos_context, error_message);
Packit 79f644
}
Packit 79f644
Packit 79f644
char *
Packit 79f644
goa_kerberos_identity_get_principal_name (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  krb5_principal principal;
Packit 79f644
  krb5_error_code error_code;
Packit 79f644
  char *unparsed_name;
Packit 79f644
  char *principal_name;
Packit 79f644
  int flags;
Packit 79f644
Packit 79f644
  if (self->priv->identifier == NULL)
Packit 79f644
    return NULL;
Packit 79f644
Packit 79f644
  error_code = krb5_parse_name (self->priv->kerberos_context,
Packit 79f644
                                self->priv->identifier,
Packit 79f644
                                &principal);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      const char *error_message;
Packit 79f644
      error_message =
Packit 79f644
        krb5_get_error_message (self->priv->kerberos_context, error_code);
Packit 79f644
      g_debug
Packit 79f644
        ("GoaKerberosIdentity: Error parsing identity %s into kerberos principal: %s",
Packit 79f644
         self->priv->identifier, error_message);
Packit 79f644
      krb5_free_error_message (self->priv->kerberos_context, error_message);
Packit 79f644
      return NULL;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  flags = KRB5_PRINCIPAL_UNPARSE_DISPLAY;
Packit 79f644
  error_code = krb5_unparse_name_flags (self->priv->kerberos_context,
Packit 79f644
                                        principal, flags, &unparsed_name);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      const char *error_message;
Packit 79f644
Packit 79f644
      error_message =
Packit 79f644
        krb5_get_error_message (self->priv->kerberos_context, error_code);
Packit 79f644
      g_debug ("GoaKerberosIdentity: Error parsing principal identity name: %s",
Packit 79f644
               error_message);
Packit 79f644
      krb5_free_error_message (self->priv->kerberos_context, error_message);
Packit 79f644
      return NULL;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  principal_name = g_strdup (unparsed_name);
Packit 79f644
  krb5_free_unparsed_name (self->priv->kerberos_context, unparsed_name);
Packit 79f644
Packit 79f644
  return principal_name;
Packit 79f644
}
Packit 79f644
Packit 79f644
char *
Packit 79f644
goa_kerberos_identity_get_realm_name (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  krb5_principal principal;
Packit 79f644
  krb5_error_code error_code;
Packit 79f644
  krb5_data *realm;
Packit 79f644
  char *realm_name;
Packit 79f644
Packit 79f644
  if (self->priv->identifier == NULL)
Packit 79f644
    return NULL;
Packit 79f644
Packit 79f644
  error_code = krb5_parse_name (self->priv->kerberos_context,
Packit 79f644
                                self->priv->identifier, &principal);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      const char *error_message;
Packit 79f644
      error_message =
Packit 79f644
        krb5_get_error_message (self->priv->kerberos_context, error_code);
Packit 79f644
      g_debug
Packit 79f644
        ("GoaKerberosIdentity: Error parsing identity %s into kerberos principal: %s",
Packit 79f644
         self->priv->identifier, error_message);
Packit 79f644
      krb5_free_error_message (self->priv->kerberos_context, error_message);
Packit 79f644
      return NULL;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  realm = krb5_princ_realm (self->priv->kerberos_context, principal);
Packit 79f644
  realm_name = g_strndup (realm->data, realm->length);
Packit 79f644
  krb5_free_principal (self->priv->kerberos_context, principal);
Packit 79f644
Packit 79f644
  return realm_name;
Packit 79f644
}
Packit 79f644
Packit 79f644
char *
Packit 79f644
goa_kerberos_identity_get_preauthentication_source (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  return g_strdup (self->priv->preauth_identity_source);
Packit 79f644
}
Packit 79f644
Packit 79f644
static const char *
Packit 79f644
goa_kerberos_identity_get_identifier (GoaIdentity *identity)
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity *self = GOA_KERBEROS_IDENTITY (identity);
Packit 79f644
Packit 79f644
  return self->priv->identifier;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
credentials_validate_existence (GoaKerberosIdentity *self,
Packit 79f644
                                krb5_principal principal, krb5_creds * credentials)
Packit 79f644
{
Packit 79f644
  /* Checks if default principal associated with the cache has a valid
Packit 79f644
   * ticket granting ticket in the passed in credentials
Packit 79f644
   */
Packit 79f644
Packit 79f644
  if (krb5_is_config_principal (self->priv->kerberos_context, credentials->server))
Packit 79f644
    return FALSE;
Packit 79f644
Packit 79f644
  /* looking for the krbtgt / REALM pair, so it should be exactly 2 items */
Packit 79f644
  if (krb5_princ_size (self->priv->kerberos_context, credentials->server) != 2)
Packit 79f644
    return FALSE;
Packit 79f644
Packit 79f644
  if (!krb5_realm_compare (self->priv->kerberos_context,
Packit 79f644
                           credentials->server, principal))
Packit 79f644
    {
Packit 79f644
      /* credentials are from some other realm */
Packit 79f644
      return FALSE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (strncmp (credentials->server->data[0].data,
Packit 79f644
               KRB5_TGS_NAME, credentials->server->data[0].length) != 0)
Packit 79f644
    {
Packit 79f644
      /* credentials aren't for ticket granting */
Packit 79f644
      return FALSE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (credentials->server->data[1].length != principal->realm.length ||
Packit 79f644
      memcmp (credentials->server->data[1].data,
Packit 79f644
              principal->realm.data, principal->realm.length) != 0)
Packit 79f644
    {
Packit 79f644
      /* credentials are for some other realm */
Packit 79f644
      return FALSE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return TRUE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
snoop_preauth_identity_from_credentials (GoaKerberosIdentity  *self,
Packit 79f644
                                         krb5_creds           *credentials,
Packit 79f644
                                         char                **identity_source)
Packit 79f644
{
Packit 79f644
  GRegex *regex;
Packit 79f644
  GMatchInfo *match_info = NULL;
Packit 79f644
  gboolean identity_source_exposed = FALSE;
Packit 79f644
Packit 79f644
  if (!krb5_is_config_principal (self->priv->kerberos_context, credentials->server))
Packit 79f644
    return FALSE;
Packit 79f644
Packit 79f644
  regex = g_regex_new ("\"X509_user_identity\":\"(?P<identity_source>[^\"]*)\"",
Packit 79f644
                        G_REGEX_MULTILINE | G_REGEX_CASELESS | G_REGEX_RAW,
Packit 79f644
                        0,
Packit 79f644
                        NULL);
Packit 79f644
Packit 79f644
  if (regex == NULL)
Packit 79f644
    return FALSE;
Packit 79f644
Packit 79f644
  g_regex_match_full (regex, credentials->ticket.data, credentials->ticket.length, 0, 0, &match_info, NULL);
Packit 79f644
Packit 79f644
  if (match_info != NULL && g_match_info_matches (match_info))
Packit 79f644
    {
Packit 79f644
      if (identity_source)
Packit 79f644
        {
Packit 79f644
          g_free (*identity_source);
Packit 79f644
          *identity_source = g_match_info_fetch_named (match_info, "identity_source");
Packit 79f644
        }
Packit 79f644
      identity_source_exposed = TRUE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  g_match_info_free (match_info);
Packit 79f644
  g_regex_unref (regex);
Packit 79f644
Packit 79f644
  return identity_source_exposed;
Packit 79f644
}
Packit 79f644
Packit 79f644
static krb5_timestamp
Packit 79f644
get_current_time (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  krb5_timestamp current_time;
Packit 79f644
  krb5_error_code error_code;
Packit 79f644
Packit 79f644
  error_code = krb5_timeofday (self->priv->kerberos_context, &current_time);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      const char *error_message;
Packit 79f644
Packit 79f644
      error_message =
Packit 79f644
        krb5_get_error_message (self->priv->kerberos_context, error_code);
Packit 79f644
      g_debug ("GoaKerberosIdentity: Error getting current time: %s", error_message);
Packit 79f644
      krb5_free_error_message (self->priv->kerberos_context, error_message);
Packit 79f644
      return 0;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return current_time;
Packit 79f644
}
Packit 79f644
Packit 79f644
typedef struct
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity *self;
Packit 79f644
  guint *idle_id;
Packit 79f644
  const char *property_name;
Packit 79f644
} NotifyRequest;
Packit 79f644
Packit 79f644
static void
Packit 79f644
clear_idle_id (NotifyRequest *request)
Packit 79f644
{
Packit 79f644
  *request->idle_id = 0;
Packit 79f644
  g_object_unref (request->self);
Packit 79f644
  g_slice_free (NotifyRequest, request);
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
on_notify_queued (NotifyRequest *request)
Packit 79f644
{
Packit 79f644
  g_object_notify (G_OBJECT (request->self), request->property_name);
Packit 79f644
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
queue_notify (GoaKerberosIdentity *self,
Packit 79f644
              guint               *idle_id,
Packit 79f644
              const char          *property_name)
Packit 79f644
{
Packit 79f644
  NotifyRequest *request;
Packit 79f644
Packit 79f644
  if (*idle_id != 0)
Packit 79f644
    {
Packit 79f644
      return;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  request = g_slice_new0 (NotifyRequest);
Packit 79f644
  request->self = g_object_ref (self);
Packit 79f644
  request->idle_id = idle_id;
Packit 79f644
  request->property_name = property_name;
Packit 79f644
Packit 79f644
  *idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
Packit 79f644
                              (GSourceFunc)
Packit 79f644
                              on_notify_queued,
Packit 79f644
                              request,
Packit 79f644
                              (GDestroyNotify)
Packit 79f644
                              clear_idle_id);
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
set_start_time (GoaKerberosIdentity *self,
Packit 79f644
                krb5_timestamp       start_time)
Packit 79f644
{
Packit 79f644
  if (self->priv->start_time != start_time)
Packit 79f644
    {
Packit 79f644
      self->priv->start_time = start_time;
Packit 79f644
      queue_notify (self,
Packit 79f644
                    &self->priv->start_time_idle_id,
Packit 79f644
                    "start-timestamp");
Packit 79f644
      return TRUE;
Packit 79f644
    }
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
set_renewal_time (GoaKerberosIdentity *self,
Packit 79f644
                  krb5_timestamp       renewal_time)
Packit 79f644
{
Packit 79f644
  if (self->priv->renewal_time != renewal_time)
Packit 79f644
    {
Packit 79f644
      self->priv->renewal_time = renewal_time;
Packit 79f644
      queue_notify (self,
Packit 79f644
                    &self->priv->renewal_time_idle_id,
Packit 79f644
                    "renewal-timestamp");
Packit 79f644
      return TRUE;
Packit 79f644
    }
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
set_expiration_time (GoaKerberosIdentity *self,
Packit 79f644
                     krb5_timestamp       expiration_time)
Packit 79f644
{
Packit 79f644
  if (self->priv->expiration_time != expiration_time)
Packit 79f644
    {
Packit 79f644
      self->priv->expiration_time = expiration_time;
Packit 79f644
      queue_notify (self,
Packit 79f644
                    &self->priv->expiration_time_idle_id,
Packit 79f644
                    "expiration-timestamp");
Packit 79f644
      return TRUE;
Packit 79f644
    }
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
examine_credentials (GoaKerberosIdentity *self,
Packit 79f644
                     krb5_creds          *credentials,
Packit 79f644
                     krb5_timestamp      *start_time,
Packit 79f644
                     krb5_timestamp      *renewal_time,
Packit 79f644
                     krb5_timestamp      *expiration_time,
Packit 79f644
                     gboolean            *are_expired)
Packit 79f644
{
Packit 79f644
  krb5_timestamp credentials_start_time;
Packit 79f644
  krb5_timestamp credentials_end_time;
Packit 79f644
  krb5_timestamp current_time;
Packit 79f644
Packit 79f644
  G_LOCK (identity_lock);
Packit 79f644
Packit 79f644
  if (credentials->times.starttime != 0)
Packit 79f644
    credentials_start_time = credentials->times.starttime;
Packit 79f644
  else
Packit 79f644
    credentials_start_time = credentials->times.authtime;
Packit 79f644
Packit 79f644
  *renewal_time = credentials->times.renew_till;
Packit 79f644
Packit 79f644
  credentials_end_time = credentials->times.endtime;
Packit 79f644
Packit 79f644
  if (self->priv->start_time == 0)
Packit 79f644
    *start_time = credentials_start_time;
Packit 79f644
  else
Packit 79f644
    *start_time = MIN (self->priv->start_time,
Packit 79f644
                       credentials_start_time);
Packit 79f644
  *expiration_time = MAX (credentials->times.endtime,
Packit 79f644
                          self->priv->expiration_time);
Packit 79f644
  G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
  current_time = get_current_time (self);
Packit 79f644
Packit 79f644
  if (current_time < credentials_start_time ||
Packit 79f644
      credentials_end_time <= current_time)
Packit 79f644
    *are_expired = TRUE;
Packit 79f644
  else
Packit 79f644
    *are_expired = FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static VerificationLevel
Packit 79f644
verify_identity (GoaKerberosIdentity  *self,
Packit 79f644
                 char                **preauth_identity_source,
Packit 79f644
                 GError              **error)
Packit 79f644
{
Packit 79f644
  krb5_principal principal = NULL;
Packit 79f644
  krb5_cc_cursor cursor;
Packit 79f644
  krb5_creds credentials;
Packit 79f644
  krb5_error_code error_code;
Packit 79f644
  krb5_timestamp start_time = 0;
Packit 79f644
  krb5_timestamp renewal_time = 0;
Packit 79f644
  krb5_timestamp expiration_time = 0;
Packit 79f644
  VerificationLevel verification_level = VERIFICATION_LEVEL_UNVERIFIED;
Packit 79f644
Packit 79f644
  if (self->priv->credentials_cache == NULL)
Packit 79f644
    goto out;
Packit 79f644
Packit 79f644
  error_code = krb5_cc_get_principal (self->priv->kerberos_context,
Packit 79f644
                                      self->priv->credentials_cache,
Packit 79f644
                                      &principal);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      if (error_code == KRB5_CC_END || error_code == KRB5_FCC_NOFILE)
Packit 79f644
        goto out;
Packit 79f644
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_NOT_FOUND,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 _("Could not find identity in credential cache: "));
Packit 79f644
      verification_level = VERIFICATION_LEVEL_ERROR;
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  error_code = krb5_cc_start_seq_get (self->priv->kerberos_context,
Packit 79f644
                                      self->priv->credentials_cache, &cursor);
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_CREDENTIALS_UNAVAILABLE,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 _("Could not find identity credentials in cache: "));
Packit 79f644
Packit 79f644
      verification_level = VERIFICATION_LEVEL_ERROR;
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  verification_level = VERIFICATION_LEVEL_UNVERIFIED;
Packit 79f644
Packit 79f644
  error_code = krb5_cc_next_cred (self->priv->kerberos_context,
Packit 79f644
                                  self->priv->credentials_cache,
Packit 79f644
                                  &cursor,
Packit 79f644
                                  &credentials);
Packit 79f644
Packit 79f644
  while (error_code == 0)
Packit 79f644
    {
Packit 79f644
      if (credentials_validate_existence (self, principal, &credentials))
Packit 79f644
        {
Packit 79f644
          gboolean credentials_are_expired = TRUE;
Packit 79f644
Packit 79f644
          examine_credentials (self, &credentials,
Packit 79f644
                               &start_time,
Packit 79f644
                               &renewal_time,
Packit 79f644
                               &expiration_time,
Packit 79f644
                               &credentials_are_expired);
Packit 79f644
Packit 79f644
          if (!credentials_are_expired)
Packit 79f644
            verification_level = VERIFICATION_LEVEL_SIGNED_IN;
Packit 79f644
          else
Packit 79f644
            verification_level = VERIFICATION_LEVEL_EXISTS;
Packit 79f644
        }
Packit 79f644
      else
Packit 79f644
        {
Packit 79f644
          snoop_preauth_identity_from_credentials (self, &credentials, preauth_identity_source);
Packit 79f644
        }
Packit 79f644
Packit 79f644
      krb5_free_cred_contents (self->priv->kerberos_context, &credentials);
Packit 79f644
Packit 79f644
      error_code = krb5_cc_next_cred (self->priv->kerberos_context,
Packit 79f644
                                      self->priv->credentials_cache,
Packit 79f644
                                      &cursor,
Packit 79f644
                                      &credentials);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (error_code != KRB5_CC_END)
Packit 79f644
    {
Packit 79f644
      verification_level = VERIFICATION_LEVEL_ERROR;
Packit 79f644
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_ENUMERATING_CREDENTIALS,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 _("Could not sift through identity credentials in cache: "));
Packit 79f644
      goto end_sequence;
Packit 79f644
    }
Packit 79f644
Packit 79f644
 end_sequence:
Packit 79f644
  error_code = krb5_cc_end_seq_get (self->priv->kerberos_context,
Packit 79f644
                                    self->priv->credentials_cache,
Packit 79f644
                                    &cursor);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      verification_level = VERIFICATION_LEVEL_ERROR;
Packit 79f644
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_ENUMERATING_CREDENTIALS,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 _("Could not finish up sifting through "
Packit 79f644
                                                   "identity credentials in cache: "));
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
out:
Packit 79f644
Packit 79f644
  G_LOCK (identity_lock);
Packit 79f644
  set_start_time (self, start_time);
Packit 79f644
  set_renewal_time (self, renewal_time);
Packit 79f644
  set_expiration_time (self, expiration_time);
Packit 79f644
  G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
  if (principal != NULL)
Packit 79f644
    krb5_free_principal (self->priv->kerberos_context, principal);
Packit 79f644
  return verification_level;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_kerberos_identity_is_signed_in (GoaIdentity *identity)
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity *self = GOA_KERBEROS_IDENTITY (identity);
Packit 79f644
  gboolean is_signed_in = FALSE;
Packit 79f644
Packit 79f644
  G_LOCK (identity_lock);
Packit 79f644
  if (self->priv->cached_verification_level == VERIFICATION_LEVEL_SIGNED_IN)
Packit 79f644
    is_signed_in = TRUE;
Packit 79f644
  G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
  return is_signed_in;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
identity_interface_init (GoaIdentityInterface *interface)
Packit 79f644
{
Packit 79f644
  interface->get_identifier = goa_kerberos_identity_get_identifier;
Packit 79f644
  interface->is_signed_in = goa_kerberos_identity_is_signed_in;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
on_expiration_alarm_fired (GoaAlarm            *alarm,
Packit 79f644
                           GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_ALARM (alarm));
Packit 79f644
  g_return_if_fail (GOA_IS_KERBEROS_IDENTITY (self));
Packit 79f644
Packit 79f644
  g_debug ("GoaKerberosIdentity: expiration alarm fired for identity %s",
Packit 79f644
           goa_identity_get_identifier (GOA_IDENTITY (self)));
Packit 79f644
  g_signal_emit (G_OBJECT (self), signals[NEEDS_REFRESH], 0);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
on_expiration_alarm_rearmed (GoaAlarm            *alarm,
Packit 79f644
                             GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_ALARM (alarm));
Packit 79f644
  g_return_if_fail (GOA_IS_KERBEROS_IDENTITY (self));
Packit 79f644
Packit 79f644
  g_debug ("GoaKerberosIdentity: expiration alarm rearmed");
Packit 79f644
  g_signal_emit (G_OBJECT (self), signals[NEEDS_REFRESH], 0);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
on_renewal_alarm_rearmed (GoaAlarm            *alarm,
Packit 79f644
                          GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_ALARM (alarm));
Packit 79f644
  g_return_if_fail (GOA_IS_KERBEROS_IDENTITY (self));
Packit 79f644
Packit 79f644
  g_debug ("GoaKerberosIdentity: renewal alarm rearmed");
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
on_renewal_alarm_fired (GoaAlarm            *alarm,
Packit 79f644
                        GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_ALARM (alarm));
Packit 79f644
  g_return_if_fail (GOA_IS_KERBEROS_IDENTITY (self));
Packit 79f644
Packit 79f644
  if (self->priv->cached_verification_level == VERIFICATION_LEVEL_SIGNED_IN)
Packit 79f644
    {
Packit 79f644
      g_debug ("GoaKerberosIdentity: renewal alarm fired for signed-in identity");
Packit 79f644
      g_signal_emit (G_OBJECT (self), signals[NEEDS_RENEWAL], 0);
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
on_expiring_alarm_rearmed (GoaAlarm            *alarm,
Packit 79f644
                           GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_ALARM (alarm));
Packit 79f644
  g_return_if_fail (GOA_IS_KERBEROS_IDENTITY (self));
Packit 79f644
Packit 79f644
  g_debug ("GoaKerberosIdentity: expiring alarm rearmed");
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
on_expiring_alarm_fired (GoaAlarm            *alarm,
Packit 79f644
                         GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  g_return_if_fail (GOA_IS_ALARM (alarm));
Packit 79f644
  g_return_if_fail (GOA_IS_KERBEROS_IDENTITY (self));
Packit 79f644
Packit 79f644
  if (self->priv->cached_verification_level == VERIFICATION_LEVEL_SIGNED_IN)
Packit 79f644
    {
Packit 79f644
      g_debug ("GoaKerberosIdentity: expiring alarm fired for signed-in identity");
Packit 79f644
      g_signal_emit (G_OBJECT (self), signals[EXPIRING], 0);
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
unref_alarm (GoaAlarm *alarm)
Packit 79f644
{
Packit 79f644
  g_object_unref (G_OBJECT (alarm));
Packit 79f644
  return G_SOURCE_REMOVE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
clear_alarm_and_unref_on_idle (GoaKerberosIdentity  *self,
Packit 79f644
                     GoaAlarm            **alarm)
Packit 79f644
{
Packit 79f644
  if (!*alarm)
Packit 79f644
    return;
Packit 79f644
Packit 79f644
  g_idle_add ((GSourceFunc) unref_alarm, *alarm);
Packit 79f644
  *alarm = NULL;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
reset_alarm (GoaKerberosIdentity  *self,
Packit 79f644
             GoaAlarm            **alarm,
Packit 79f644
             GDateTime            *alarm_time)
Packit 79f644
{
Packit 79f644
  GDateTime *old_alarm_time = NULL;
Packit 79f644
Packit 79f644
  G_LOCK (identity_lock);
Packit 79f644
  if (*alarm)
Packit 79f644
    old_alarm_time = goa_alarm_get_time (*alarm);
Packit 79f644
  if (old_alarm_time == NULL || !g_date_time_equal (alarm_time, old_alarm_time))
Packit 79f644
    {
Packit 79f644
      clear_alarm_and_unref_on_idle (self, alarm);
Packit 79f644
      *alarm = goa_alarm_new (alarm_time);
Packit 79f644
    }
Packit 79f644
  G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
disconnect_alarm_signals (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  if (self->priv->renewal_alarm)
Packit 79f644
    {
Packit 79f644
      g_signal_handlers_disconnect_by_func (G_OBJECT (self->priv->renewal_alarm),
Packit 79f644
                                            G_CALLBACK (on_renewal_alarm_fired),
Packit 79f644
                                            self);
Packit 79f644
      g_signal_handlers_disconnect_by_func (G_OBJECT (self->priv->renewal_alarm),
Packit 79f644
                                            G_CALLBACK (on_renewal_alarm_rearmed),
Packit 79f644
                                            self);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (self->priv->expiring_alarm)
Packit 79f644
    {
Packit 79f644
      g_signal_handlers_disconnect_by_func (G_OBJECT (self->priv->expiring_alarm),
Packit 79f644
                                            G_CALLBACK (on_expiring_alarm_fired),
Packit 79f644
                                            self);
Packit 79f644
      g_signal_handlers_disconnect_by_func (G_OBJECT (self->priv->expiring_alarm),
Packit 79f644
                                            G_CALLBACK (on_expiring_alarm_rearmed),
Packit 79f644
                                            self);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (self->priv->expiration_alarm)
Packit 79f644
    {
Packit 79f644
      g_signal_handlers_disconnect_by_func (G_OBJECT (self->priv->expiration_alarm),
Packit 79f644
                                            G_CALLBACK (on_expiration_alarm_rearmed),
Packit 79f644
                                            self);
Packit 79f644
      g_signal_handlers_disconnect_by_func (G_OBJECT (self->priv->expiration_alarm),
Packit 79f644
                                            G_CALLBACK (on_expiration_alarm_fired),
Packit 79f644
                                            self);
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
connect_alarm_signals (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  if (self->priv->renewal_alarm)
Packit 79f644
    {
Packit 79f644
      g_signal_connect (G_OBJECT (self->priv->renewal_alarm),
Packit 79f644
                        "fired",
Packit 79f644
                        G_CALLBACK (on_renewal_alarm_fired),
Packit 79f644
                        self);
Packit 79f644
      g_signal_connect (G_OBJECT (self->priv->renewal_alarm),
Packit 79f644
                        "rearmed",
Packit 79f644
                        G_CALLBACK (on_renewal_alarm_rearmed),
Packit 79f644
                        self);
Packit 79f644
    }
Packit 79f644
  g_signal_connect (G_OBJECT (self->priv->expiring_alarm),
Packit 79f644
                    "fired",
Packit 79f644
                    G_CALLBACK (on_expiring_alarm_fired),
Packit 79f644
                    self);
Packit 79f644
  g_signal_connect (G_OBJECT (self->priv->expiring_alarm),
Packit 79f644
                    "rearmed",
Packit 79f644
                    G_CALLBACK (on_expiring_alarm_rearmed),
Packit 79f644
                    self);
Packit 79f644
  g_signal_connect (G_OBJECT (self->priv->expiration_alarm),
Packit 79f644
                    "fired",
Packit 79f644
                    G_CALLBACK (on_expiration_alarm_fired),
Packit 79f644
                    self);
Packit 79f644
  g_signal_connect (G_OBJECT (self->priv->expiration_alarm),
Packit 79f644
                    "rearmed",
Packit 79f644
                    G_CALLBACK (on_expiration_alarm_rearmed),
Packit 79f644
                    self);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
reset_alarms (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  GDateTime *start_time = NULL;
Packit 79f644
  GDateTime *expiration_time = NULL;
Packit 79f644
  GDateTime *expiring_time = NULL;
Packit 79f644
  GDateTime *latest_possible_renewal_time = NULL;
Packit 79f644
  GDateTime *renewal_time = NULL;
Packit 79f644
Packit 79f644
  G_LOCK (identity_lock);
Packit 79f644
  start_time = g_date_time_new_from_unix_local (self->priv->start_time);
Packit 79f644
  if (self->priv->renewal_time != 0)
Packit 79f644
    latest_possible_renewal_time = g_date_time_new_from_unix_local (self->priv->renewal_time);
Packit 79f644
  expiration_time = g_date_time_new_from_unix_local (self->priv->expiration_time);
Packit 79f644
  G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
  /* Let the user reauthenticate 10 min before expiration */
Packit 79f644
  expiring_time = g_date_time_add_minutes (expiration_time, -10);
Packit 79f644
Packit 79f644
  if (latest_possible_renewal_time != NULL)
Packit 79f644
    {
Packit 79f644
      GTimeSpan lifespan;
Packit 79f644
Packit 79f644
      lifespan = g_date_time_difference (expiration_time, start_time);
Packit 79f644
Packit 79f644
      /* Try to quietly auto-renew halfway through so in ideal configurations
Packit 79f644
       * the ticket is never more than halfway to unrenewable
Packit 79f644
       */
Packit 79f644
      renewal_time = g_date_time_add (start_time, lifespan / 2);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  disconnect_alarm_signals (self);
Packit 79f644
Packit 79f644
  if (renewal_time != NULL)
Packit 79f644
    reset_alarm (self, &self->priv->renewal_alarm, renewal_time);
Packit 79f644
Packit 79f644
  reset_alarm (self, &self->priv->expiring_alarm, expiring_time);
Packit 79f644
  reset_alarm (self, &self->priv->expiration_alarm, expiration_time);
Packit 79f644
Packit 79f644
  g_clear_pointer (&expiring_time, g_date_time_unref);
Packit 79f644
  g_clear_pointer (&renewal_time, g_date_time_unref);
Packit 79f644
  g_clear_pointer (&expiration_time, g_date_time_unref);
Packit 79f644
  g_clear_pointer (&latest_possible_renewal_time, g_date_time_unref);
Packit 79f644
  g_clear_pointer (&start_time, g_date_time_unref);
Packit 79f644
Packit 79f644
  connect_alarm_signals (self);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
clear_alarms (GoaKerberosIdentity *self)
Packit 79f644
{
Packit 79f644
  disconnect_alarm_signals (self);
Packit 79f644
  clear_alarm_and_unref_on_idle (self, &self->priv->renewal_alarm);
Packit 79f644
  clear_alarm_and_unref_on_idle (self, &self->priv->expiring_alarm);
Packit 79f644
  clear_alarm_and_unref_on_idle (self, &self->priv->expiration_alarm);
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_kerberos_identity_initable_init (GInitable     *initable,
Packit 79f644
                                     GCancellable  *cancellable,
Packit 79f644
                                     GError       **error)
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity *self = GOA_KERBEROS_IDENTITY (initable);
Packit 79f644
  GError *verification_error;
Packit 79f644
Packit 79f644
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
Packit 79f644
    return FALSE;
Packit 79f644
Packit 79f644
  if (self->priv->identifier == NULL)
Packit 79f644
    {
Packit 79f644
      self->priv->identifier = get_identifier (self, error);
Packit 79f644
Packit 79f644
      if (self->priv->identifier != NULL)
Packit 79f644
        queue_notify (self, &self->priv->identifier_idle_id, "identifier");
Packit 79f644
    }
Packit 79f644
Packit 79f644
  verification_error = NULL;
Packit 79f644
  self->priv->cached_verification_level =
Packit 79f644
    verify_identity (self, &self->priv->preauth_identity_source, &verification_error);
Packit 79f644
Packit 79f644
  switch (self->priv->cached_verification_level)
Packit 79f644
    {
Packit 79f644
    case VERIFICATION_LEVEL_EXISTS:
Packit 79f644
    case VERIFICATION_LEVEL_SIGNED_IN:
Packit 79f644
      reset_alarms (self);
Packit 79f644
Packit 79f644
      queue_notify (self, &self->priv->is_signed_in_idle_id, "is-signed-in");
Packit 79f644
      return TRUE;
Packit 79f644
Packit 79f644
    case VERIFICATION_LEVEL_UNVERIFIED:
Packit 79f644
      return TRUE;
Packit 79f644
Packit 79f644
    case VERIFICATION_LEVEL_ERROR:
Packit 79f644
    default:
Packit 79f644
      if (verification_error != NULL)
Packit 79f644
        {
Packit 79f644
          g_propagate_error (error, verification_error);
Packit 79f644
          return FALSE;
Packit 79f644
        }
Packit 79f644
Packit 79f644
      g_set_error (error,
Packit 79f644
                   GOA_IDENTITY_ERROR,
Packit 79f644
                   GOA_IDENTITY_ERROR_VERIFYING,
Packit 79f644
                   _("No associated identification found"));
Packit 79f644
      return FALSE;
Packit 79f644
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
initable_interface_init (GInitableIface *interface)
Packit 79f644
{
Packit 79f644
  interface->init = goa_kerberos_identity_initable_init;
Packit 79f644
}
Packit 79f644
Packit 79f644
typedef struct
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity    *identity;
Packit 79f644
  GoaIdentityInquiryFunc  inquiry_func;
Packit 79f644
  gpointer                inquiry_data;
Packit 79f644
  GDestroyNotify          destroy_notify;
Packit 79f644
  GCancellable           *cancellable;
Packit 79f644
} SignInOperation;
Packit 79f644
Packit 79f644
static krb5_error_code
Packit 79f644
on_kerberos_inquiry (krb5_context      kerberos_context,
Packit 79f644
                     SignInOperation  *operation,
Packit 79f644
                     const char       *name,
Packit 79f644
                     const char       *banner,
Packit 79f644
                     int               number_of_prompts,
Packit 79f644
                     krb5_prompt       prompts[])
Packit 79f644
{
Packit 79f644
  GoaIdentityInquiry *inquiry;
Packit 79f644
  krb5_error_code error_code;
Packit 79f644
Packit 79f644
  inquiry = goa_kerberos_identity_inquiry_new (operation->identity,
Packit 79f644
                                               name,
Packit 79f644
                                               banner,
Packit 79f644
                                               prompts,
Packit 79f644
                                               number_of_prompts);
Packit 79f644
Packit 79f644
  operation->inquiry_func (inquiry,
Packit 79f644
                           operation->cancellable,
Packit 79f644
                           operation->inquiry_data);
Packit 79f644
Packit 79f644
  if (goa_identity_inquiry_is_failed (inquiry))
Packit 79f644
    error_code = KRB5_LIBOS_CANTREADPWD;
Packit 79f644
  else if (!goa_identity_inquiry_is_complete (inquiry))
Packit 79f644
    g_cancellable_cancel (operation->cancellable);
Packit 79f644
Packit 79f644
  if (g_cancellable_is_cancelled (operation->cancellable))
Packit 79f644
    error_code = KRB5_LIBOS_PWDINTR;
Packit 79f644
  else
Packit 79f644
    error_code = 0;
Packit 79f644
Packit 79f644
  g_object_unref (inquiry);
Packit 79f644
Packit 79f644
  return error_code;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
create_credential_cache (GoaKerberosIdentity  *self,
Packit 79f644
                         GError              **error)
Packit 79f644
{
Packit 79f644
  krb5_ccache      default_cache;
Packit 79f644
  const char      *cache_type;
Packit 79f644
  krb5_error_code  error_code;
Packit 79f644
Packit 79f644
  error_code = krb5_cc_default (self->priv->kerberos_context, &default_cache);
Packit 79f644
Packit 79f644
  if (error_code == 0)
Packit 79f644
    {
Packit 79f644
      cache_type = krb5_cc_get_type (self->priv->kerberos_context, default_cache);
Packit 79f644
Packit 79f644
      error_code = krb5_cc_new_unique (self->priv->kerberos_context,
Packit 79f644
                                       cache_type,
Packit 79f644
                                       NULL,
Packit 79f644
                                       &self->priv->credentials_cache);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_ALLOCATING_CREDENTIALS,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 _("Could not create credential cache: "));
Packit 79f644
Packit 79f644
      return FALSE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return TRUE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
goa_kerberos_identity_update_credentials (GoaKerberosIdentity  *self,
Packit 79f644
                                          krb5_principal        principal,
Packit 79f644
                                          krb5_creds           *new_credentials,
Packit 79f644
                                          GError              **error)
Packit 79f644
{
Packit 79f644
  krb5_error_code   error_code;
Packit 79f644
Packit 79f644
  if (self->priv->credentials_cache == NULL)
Packit 79f644
    {
Packit 79f644
      if (!create_credential_cache (self, error))
Packit 79f644
        {
Packit 79f644
          krb5_free_cred_contents (self->priv->kerberos_context, new_credentials);
Packit 79f644
          goto out;
Packit 79f644
        }
Packit 79f644
    }
Packit 79f644
Packit 79f644
  error_code = krb5_cc_initialize (self->priv->kerberos_context,
Packit 79f644
                                   self->priv->credentials_cache,
Packit 79f644
                                   principal);
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_ALLOCATING_CREDENTIALS,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 _("Could not initialize credentials cache: "));
Packit 79f644
Packit 79f644
      krb5_free_cred_contents (self->priv->kerberos_context, new_credentials);
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  error_code = krb5_cc_store_cred (self->priv->kerberos_context,
Packit 79f644
                                   self->priv->credentials_cache,
Packit 79f644
                                   new_credentials);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_SAVING_CREDENTIALS,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 _("Could not store new credentials in credentials cache: "));
Packit 79f644
Packit 79f644
      krb5_free_cred_contents (self->priv->kerberos_context, new_credentials);
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
  krb5_free_cred_contents (self->priv->kerberos_context, new_credentials);
Packit 79f644
Packit 79f644
  return TRUE;
Packit 79f644
out:
Packit 79f644
  return FALSE;
Packit 79f644
}
Packit 79f644
Packit 79f644
static SignInOperation *
Packit 79f644
sign_in_operation_new (GoaKerberosIdentity    *identity,
Packit 79f644
                       GoaIdentityInquiryFunc  inquiry_func,
Packit 79f644
                       gpointer                inquiry_data,
Packit 79f644
                       GDestroyNotify          destroy_notify,
Packit 79f644
                       GCancellable           *cancellable)
Packit 79f644
{
Packit 79f644
  SignInOperation *operation;
Packit 79f644
Packit 79f644
  operation = g_slice_new0 (SignInOperation);
Packit 79f644
  operation->identity = g_object_ref (identity);
Packit 79f644
  operation->inquiry_func = inquiry_func;
Packit 79f644
  operation->inquiry_data = inquiry_data;
Packit 79f644
  operation->destroy_notify = destroy_notify;
Packit 79f644
Packit 79f644
  if (cancellable == NULL)
Packit 79f644
    operation->cancellable = g_cancellable_new ();
Packit 79f644
  else
Packit 79f644
    operation->cancellable = g_object_ref (cancellable);
Packit 79f644
Packit 79f644
  return operation;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
sign_in_operation_free (SignInOperation *operation)
Packit 79f644
{
Packit 79f644
  g_object_unref (operation->identity);
Packit 79f644
  g_object_unref (operation->cancellable);
Packit 79f644
Packit 79f644
  g_slice_free (SignInOperation, operation);
Packit 79f644
}
Packit 79f644
Packit 79f644
gboolean
Packit 79f644
goa_kerberos_identity_sign_in (GoaKerberosIdentity     *self,
Packit 79f644
                               const char              *principal_name,
Packit 79f644
                               gconstpointer            initial_password,
Packit 79f644
                               const char              *preauth_source,
Packit 79f644
                               GoaIdentitySignInFlags   flags,
Packit 79f644
                               GoaIdentityInquiryFunc   inquiry_func,
Packit 79f644
                               gpointer                 inquiry_data,
Packit 79f644
                               GDestroyNotify           destroy_notify,
Packit 79f644
                               GCancellable            *cancellable,
Packit 79f644
                               GError                 **error)
Packit 79f644
{
Packit 79f644
  SignInOperation *operation;
Packit 79f644
  krb5_principal principal;
Packit 79f644
  krb5_error_code error_code;
Packit 79f644
  krb5_creds new_credentials;
Packit 79f644
  krb5_get_init_creds_opt *options;
Packit 79f644
  krb5_deltat start_time;
Packit 79f644
  char *service_name;
Packit 79f644
  gboolean signed_in;
Packit 79f644
Packit 79f644
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
Packit 79f644
    return FALSE;
Packit 79f644
Packit 79f644
  error_code = krb5_get_init_creds_opt_alloc (self->priv->kerberos_context,
Packit 79f644
                                              &options);
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_ALLOCATING_CREDENTIALS,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 "%s",
Packit 79f644
                                                 ""); /* Silence -Wformat-zero-length */
Packit 79f644
      if (destroy_notify)
Packit 79f644
        destroy_notify (inquiry_data);
Packit 79f644
      return FALSE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  signed_in = FALSE;
Packit 79f644
Packit 79f644
  operation = sign_in_operation_new (self,
Packit 79f644
                                     inquiry_func,
Packit 79f644
                                     inquiry_data,
Packit 79f644
                                     destroy_notify,
Packit 79f644
                                     cancellable);
Packit 79f644
Packit 79f644
  if (g_strcmp0 (self->priv->identifier, principal_name) != 0)
Packit 79f644
    {
Packit 79f644
      g_free (self->priv->identifier);
Packit 79f644
      self->priv->identifier = g_strdup (principal_name);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  error_code = krb5_parse_name (self->priv->kerberos_context,
Packit 79f644
                                principal_name,
Packit 79f644
                                &principal);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_PARSING_IDENTIFIER,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 "%s",
Packit 79f644
                                                 ""); /* Silence -Wformat-zero-length */
Packit 79f644
      if (destroy_notify)
Packit 79f644
        destroy_notify (inquiry_data);
Packit 79f644
      return FALSE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if ((flags & GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_FORWARDING) == 0)
Packit 79f644
    krb5_get_init_creds_opt_set_forwardable (options, TRUE);
Packit 79f644
Packit 79f644
  if ((flags & GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_PROXYING) == 0)
Packit 79f644
    krb5_get_init_creds_opt_set_proxiable (options, TRUE);
Packit 79f644
Packit 79f644
  if ((flags & GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_RENEWAL) == 0)
Packit 79f644
    krb5_get_init_creds_opt_set_renew_life (options, G_MAXINT);
Packit 79f644
Packit 79f644
  if (preauth_source != NULL)
Packit 79f644
    {
Packit 79f644
      krb5_get_init_creds_opt_set_pa (self->priv->kerberos_context,
Packit 79f644
                                      options,
Packit 79f644
                                      "X509_user_identity", preauth_source);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  /* Poke glibc in case the network changed
Packit 79f644
   */
Packit 79f644
  res_init ();
Packit 79f644
Packit 79f644
  start_time = 0;
Packit 79f644
  service_name = NULL;
Packit 79f644
  error_code = krb5_get_init_creds_password (self->priv->kerberos_context,
Packit 79f644
                                             &new_credentials,
Packit 79f644
                                             principal,
Packit 79f644
                                             (char *)
Packit 79f644
                                             initial_password,
Packit 79f644
                                             (krb5_prompter_fct)
Packit 79f644
                                             on_kerberos_inquiry,
Packit 79f644
                                             operation,
Packit 79f644
                                             start_time,
Packit 79f644
                                             service_name,
Packit 79f644
                                             options);
Packit 79f644
Packit 79f644
  if (error_code == KRB5_LIBOS_PWDINTR)
Packit 79f644
    g_cancellable_cancel (operation->cancellable);
Packit 79f644
Packit 79f644
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
Packit 79f644
    {
Packit 79f644
      if (destroy_notify)
Packit 79f644
        destroy_notify (inquiry_data);
Packit 79f644
      sign_in_operation_free (operation);
Packit 79f644
Packit 79f644
      krb5_free_principal (self->priv->kerberos_context, principal);
Packit 79f644
      goto done;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_AUTHENTICATION_FAILED,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 "%s",
Packit 79f644
                                                 ""); /* Silence -Wformat-zero-length */
Packit 79f644
      if (destroy_notify)
Packit 79f644
        destroy_notify (inquiry_data);
Packit 79f644
      sign_in_operation_free (operation);
Packit 79f644
Packit 79f644
      krb5_free_principal (self->priv->kerberos_context, principal);
Packit 79f644
      goto done;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (destroy_notify)
Packit 79f644
    destroy_notify (inquiry_data);
Packit 79f644
  sign_in_operation_free (operation);
Packit 79f644
Packit 79f644
  if (!goa_kerberos_identity_update_credentials (self,
Packit 79f644
                                                 principal,
Packit 79f644
                                                 &new_credentials,
Packit 79f644
                                                 error))
Packit 79f644
    {
Packit 79f644
      krb5_free_principal (self->priv->kerberos_context, principal);
Packit 79f644
      goto done;
Packit 79f644
    }
Packit 79f644
  krb5_free_principal (self->priv->kerberos_context, principal);
Packit 79f644
Packit 79f644
  g_debug ("GoaKerberosIdentity: identity signed in");
Packit 79f644
  signed_in = TRUE;
Packit 79f644
done:
Packit 79f644
Packit 79f644
  return signed_in;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
update_identifier (GoaKerberosIdentity *self, GoaKerberosIdentity *new_identity)
Packit 79f644
{
Packit 79f644
  char *new_identifier;
Packit 79f644
Packit 79f644
  new_identifier = get_identifier (self, NULL);
Packit 79f644
  if (g_strcmp0 (self->priv->identifier, new_identifier) != 0 && new_identifier != NULL)
Packit 79f644
    {
Packit 79f644
      g_free (self->priv->identifier);
Packit 79f644
      self->priv->identifier = new_identifier;
Packit 79f644
      queue_notify (self, &self->priv->identifier_idle_id, "identifier");
Packit 79f644
    }
Packit 79f644
  else
Packit 79f644
    {
Packit 79f644
      g_free (new_identifier);
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
void
Packit 79f644
goa_kerberos_identity_update (GoaKerberosIdentity *self,
Packit 79f644
                              GoaKerberosIdentity *new_identity)
Packit 79f644
{
Packit 79f644
  VerificationLevel old_verification_level, new_verification_level;
Packit 79f644
  gboolean time_changed = FALSE;
Packit 79f644
  char *preauth_identity_source = NULL;
Packit 79f644
Packit 79f644
  if (self->priv->credentials_cache != NULL)
Packit 79f644
    krb5_cc_close (self->priv->kerberos_context, self->priv->credentials_cache);
Packit 79f644
Packit 79f644
  krb5_cc_dup (new_identity->priv->kerberos_context,
Packit 79f644
               new_identity->priv->credentials_cache,
Packit 79f644
               &self->priv->credentials_cache);
Packit 79f644
Packit 79f644
  G_LOCK (identity_lock);
Packit 79f644
  update_identifier (self, new_identity);
Packit 79f644
Packit 79f644
  time_changed |= set_start_time (self, new_identity->priv->start_time);
Packit 79f644
  time_changed |= set_renewal_time (self, new_identity->priv->renewal_time);
Packit 79f644
  time_changed |= set_expiration_time (self, new_identity->priv->expiration_time);
Packit 79f644
  old_verification_level = self->priv->cached_verification_level;
Packit 79f644
  new_verification_level = new_identity->priv->cached_verification_level;
Packit 79f644
  G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
  if (time_changed)
Packit 79f644
    {
Packit 79f644
      if (new_verification_level == VERIFICATION_LEVEL_SIGNED_IN)
Packit 79f644
        reset_alarms (self);
Packit 79f644
      else
Packit 79f644
        clear_alarms (self);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  G_LOCK (identity_lock);
Packit 79f644
  g_free (self->priv->preauth_identity_source);
Packit 79f644
  self->priv->preauth_identity_source = preauth_identity_source;
Packit 79f644
  G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
  if (new_verification_level != old_verification_level)
Packit 79f644
    {
Packit 79f644
      if (old_verification_level == VERIFICATION_LEVEL_SIGNED_IN &&
Packit 79f644
          new_verification_level == VERIFICATION_LEVEL_EXISTS)
Packit 79f644
        {
Packit 79f644
          G_LOCK (identity_lock);
Packit 79f644
          self->priv->cached_verification_level = new_verification_level;
Packit 79f644
          G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
          g_signal_emit (G_OBJECT (self), signals[EXPIRED], 0);
Packit 79f644
        }
Packit 79f644
      else if (old_verification_level == VERIFICATION_LEVEL_EXISTS &&
Packit 79f644
               new_verification_level == VERIFICATION_LEVEL_SIGNED_IN)
Packit 79f644
        {
Packit 79f644
          G_LOCK (identity_lock);
Packit 79f644
          self->priv->cached_verification_level = new_verification_level;
Packit 79f644
          G_UNLOCK (identity_lock);
Packit 79f644
Packit 79f644
          g_signal_emit (G_OBJECT (self), signals[UNEXPIRED], 0);
Packit 79f644
        }
Packit 79f644
      else
Packit 79f644
        {
Packit 79f644
          G_LOCK (identity_lock);
Packit 79f644
          self->priv->cached_verification_level = new_verification_level;
Packit 79f644
          G_UNLOCK (identity_lock);
Packit 79f644
        }
Packit 79f644
      queue_notify (self, &self->priv->is_signed_in_idle_id, "is-signed-in");
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
gboolean
Packit 79f644
goa_kerberos_identity_renew (GoaKerberosIdentity *self, GError **error)
Packit 79f644
{
Packit 79f644
  krb5_error_code error_code = 0;
Packit 79f644
  krb5_principal principal;
Packit 79f644
  krb5_creds new_credentials;
Packit 79f644
  gboolean renewed = FALSE;
Packit 79f644
  char *name = NULL;
Packit 79f644
Packit 79f644
  if (self->priv->credentials_cache == NULL)
Packit 79f644
    {
Packit 79f644
      g_set_error (error,
Packit 79f644
                   GOA_IDENTITY_ERROR,
Packit 79f644
                   GOA_IDENTITY_ERROR_CREDENTIALS_UNAVAILABLE,
Packit 79f644
                   _("Could not renew identity: Not signed in"));
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  error_code = krb5_cc_get_principal (self->priv->kerberos_context,
Packit 79f644
                                      self->priv->credentials_cache, &principal);
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_CREDENTIALS_UNAVAILABLE,
Packit 79f644
                                                 error_code, _("Could not renew identity: "));
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  name = goa_kerberos_identity_get_principal_name (self);
Packit 79f644
Packit 79f644
  error_code = krb5_get_renewed_creds (self->priv->kerberos_context,
Packit 79f644
                                       &new_credentials,
Packit 79f644
                                       principal,
Packit 79f644
                                       self->priv->credentials_cache, NULL);
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_RENEWING,
Packit 79f644
                                                 error_code,
Packit 79f644
                                                 _("Could not get new credentials to renew identity %s: "),
Packit 79f644
                                                 name);
Packit 79f644
      goto free_principal;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (!goa_kerberos_identity_update_credentials (self,
Packit 79f644
                                                 principal,
Packit 79f644
                                                 &new_credentials,
Packit 79f644
                                                 error))
Packit 79f644
    {
Packit 79f644
      goto free_principal;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  g_debug ("GoaKerberosIdentity: identity %s renewed", name);
Packit 79f644
  renewed = TRUE;
Packit 79f644
Packit 79f644
free_principal:
Packit 79f644
  krb5_free_principal (self->priv->kerberos_context, principal);
Packit 79f644
Packit 79f644
out:
Packit 79f644
  g_free (name);
Packit 79f644
Packit 79f644
  return renewed;
Packit 79f644
}
Packit 79f644
Packit 79f644
gboolean
Packit 79f644
goa_kerberos_identity_erase (GoaKerberosIdentity *self, GError **error)
Packit 79f644
{
Packit 79f644
  krb5_error_code error_code = 0;
Packit 79f644
Packit 79f644
  if (self->priv->credentials_cache != NULL)
Packit 79f644
    {
Packit 79f644
      error_code = krb5_cc_destroy (self->priv->kerberos_context,
Packit 79f644
                                    self->priv->credentials_cache);
Packit 79f644
      self->priv->credentials_cache = NULL;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (error_code != 0)
Packit 79f644
    {
Packit 79f644
      set_and_prefix_error_from_krb5_error_code (self,
Packit 79f644
                                                 error,
Packit 79f644
                                                 GOA_IDENTITY_ERROR_REMOVING_CREDENTIALS,
Packit 79f644
                                                 error_code, _("Could not erase identity: "));
Packit 79f644
      return FALSE;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return TRUE;
Packit 79f644
}
Packit 79f644
Packit 79f644
GoaIdentity *
Packit 79f644
goa_kerberos_identity_new (krb5_context context, krb5_ccache cache, GError **error)
Packit 79f644
{
Packit 79f644
  GoaKerberosIdentity *self;
Packit 79f644
Packit 79f644
  self = GOA_KERBEROS_IDENTITY (g_object_new (GOA_TYPE_KERBEROS_IDENTITY, NULL));
Packit 79f644
Packit 79f644
  krb5_cc_dup (context, cache, &self->priv->credentials_cache);
Packit 79f644
  self->priv->kerberos_context = context;
Packit 79f644
Packit 79f644
  error = NULL;
Packit 79f644
  if (!g_initable_init (G_INITABLE (self), NULL, error))
Packit 79f644
    {
Packit 79f644
      g_object_unref (self);
Packit 79f644
      return NULL;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  return GOA_IDENTITY (self);
Packit 79f644
}