|
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, ¤t_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 |
}
|