[gnome-online-accounts/gnome-3-20] identity: rework how renewal time is calculated
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-online-accounts/gnome-3-20] identity: rework how renewal time is calculated
- Date: Mon, 11 Apr 2016 15:52:17 +0000 (UTC)
commit 9de1235de0927ddd47cc3cffd20fd0ba1623dee2
Author: Ray Strode <rstrode redhat com>
Date: Tue Sep 22 14:33:35 2015 -0400
identity: rework how renewal time is calculated
Right now we try to renew the kerberos ticket at the midpoint between
when we first set up the renewal alarm and when the ticket expires.
Unfortunately, this doesn't work for kernel keyring based kerberos
tickets, since the alarms are reset on a regular interval (as part
of the polling process to check for updates, since kernel keyring
doesn't have changed notification). Since the alarms are reset
regularly, the midpoint converges toward the end of the ticket
lifetime.
Instead, we should consider the ticket start time, which remains
constant. This commit tracks the ticket start time, and changes
the code renewal alarm to use the mid point between the start time
and expiration time of the ticket. We also now only set a renewal
alarm if there's a valid renewal lifetime.
https://bugzilla.gnome.org/show_bug.cgi?id=756495
(cherry picked from commit 684f5887837ce19e5331a706821b7b35cae79d4c)
src/goaidentity/goaidentity.c | 14 +++
src/goaidentity/goakerberosidentity.c | 173 ++++++++++++++++++++++++++-------
2 files changed, 150 insertions(+), 37 deletions(-)
---
diff --git a/src/goaidentity/goaidentity.c b/src/goaidentity/goaidentity.c
index 2fc491b..0ff92de 100644
--- a/src/goaidentity/goaidentity.c
+++ b/src/goaidentity/goaidentity.c
@@ -40,6 +40,20 @@ goa_identity_default_init (GoaIdentityInterface *interface)
FALSE,
G_PARAM_READABLE));
g_object_interface_install_property (interface,
+ g_param_spec_int64 ("start-timestamp",
+ "Start Timestamp",
+ "A timestamp of when the identities credentials
first became valid",
+ -1,
+ G_MAXINT64,
+ -1, G_PARAM_READABLE));
+ g_object_interface_install_property (interface,
+ g_param_spec_int64 ("renewal-timestamp",
+ "Renewal Timestamp",
+ "A timestamp of when the identities credentials
can no longer be renewed",
+ -1,
+ G_MAXINT64,
+ -1, G_PARAM_READABLE));
+ g_object_interface_install_property (interface,
g_param_spec_int64 ("expiration-timestamp",
"Expiration Timestamp",
"A timestamp of when the identities credentials
expire",
diff --git a/src/goaidentity/goakerberosidentity.c b/src/goaidentity/goakerberosidentity.c
index 6956295..57263f3 100644
--- a/src/goaidentity/goakerberosidentity.c
+++ b/src/goaidentity/goakerberosidentity.c
@@ -49,6 +49,10 @@ struct _GoaKerberosIdentityPrivate
char *preauth_identity_source;
+ krb5_timestamp start_time;
+ guint start_time_idle_id;
+ krb5_timestamp renewal_time;
+ guint renewal_time_idle_id;
krb5_timestamp expiration_time;
guint expiration_time_idle_id;
@@ -75,6 +79,8 @@ enum
PROP_0,
PROP_IDENTIFIER,
PROP_IS_SIGNED_IN,
+ PROP_START_TIMESTAMP,
+ PROP_RENEWAL_TIMESTAMP,
PROP_EXPIRATION_TIMESTAMP
};
@@ -148,6 +154,16 @@ goa_kerberos_identity_get_property (GObject *object,
g_value_set_boolean (value,
goa_kerberos_identity_is_signed_in (GOA_IDENTITY (self)));
break;
+ case PROP_START_TIMESTAMP:
+ G_LOCK (identity_lock);
+ g_value_set_int64 (value, (gint64) self->priv->start_time);
+ G_UNLOCK (identity_lock);
+ break;
+ case PROP_RENEWAL_TIMESTAMP:
+ G_LOCK (identity_lock);
+ g_value_set_int64 (value, (gint64) self->priv->renewal_time);
+ G_UNLOCK (identity_lock);
+ break;
case PROP_EXPIRATION_TIMESTAMP:
G_LOCK (identity_lock);
g_value_set_int64 (value, (gint64) self->priv->expiration_time);
@@ -221,6 +237,12 @@ goa_kerberos_identity_class_init (GoaKerberosIdentityClass *klass)
g_object_class_override_property (object_class, PROP_IDENTIFIER, "identifier");
g_object_class_override_property (object_class, PROP_IS_SIGNED_IN, "is-signed-in");
g_object_class_override_property (object_class,
+ PROP_START_TIMESTAMP,
+ "start-timestamp");
+ g_object_class_override_property (object_class,
+ PROP_RENEWAL_TIMESTAMP,
+ "renewal-timestamp");
+ g_object_class_override_property (object_class,
PROP_EXPIRATION_TIMESTAMP,
"expiration-timestamp");
@@ -573,6 +595,36 @@ queue_notify (GoaKerberosIdentity *self,
}
static gboolean
+set_start_time (GoaKerberosIdentity *self,
+ krb5_timestamp start_time)
+{
+ if (self->priv->start_time != start_time)
+ {
+ self->priv->start_time = start_time;
+ queue_notify (self,
+ &self->priv->start_time_idle_id,
+ "start-timestamp");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+set_renewal_time (GoaKerberosIdentity *self,
+ krb5_timestamp renewal_time)
+{
+ if (self->priv->renewal_time != renewal_time)
+ {
+ self->priv->renewal_time = renewal_time;
+ queue_notify (self,
+ &self->priv->renewal_time_idle_id,
+ "renewal-timestamp");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
set_expiration_time (GoaKerberosIdentity *self,
krb5_timestamp expiration_time)
{
@@ -587,26 +639,45 @@ set_expiration_time (GoaKerberosIdentity *self,
return FALSE;
}
-static gboolean
-credentials_are_expired (GoaKerberosIdentity *self,
- krb5_creds *credentials,
- krb5_timestamp *expiration_time)
+static void
+examine_credentials (GoaKerberosIdentity *self,
+ krb5_creds *credentials,
+ krb5_timestamp *start_time,
+ krb5_timestamp *renewal_time,
+ krb5_timestamp *expiration_time,
+ gboolean *are_expired)
{
+ krb5_timestamp credentials_start_time;
+ krb5_timestamp credentials_end_time;
krb5_timestamp current_time;
- current_time = get_current_time (self);
-
G_LOCK (identity_lock);
+
+ if (credentials->times.starttime != 0)
+ credentials_start_time = credentials->times.starttime;
+ else
+ credentials_start_time = credentials->times.authtime;
+
+ *renewal_time = credentials->times.renew_till;
+
+ credentials_end_time = credentials->times.endtime;
+
+ if (self->priv->start_time == 0)
+ *start_time = credentials_start_time;
+ else
+ *start_time = MIN (self->priv->start_time,
+ credentials_start_time);
*expiration_time = MAX (credentials->times.endtime,
self->priv->expiration_time);
G_UNLOCK (identity_lock);
- if (credentials->times.endtime <= current_time)
- {
- return TRUE;
- }
+ current_time = get_current_time (self);
- return FALSE;
+ if (current_time < credentials_start_time ||
+ credentials_end_time <= current_time)
+ *are_expired = TRUE;
+ else
+ *are_expired = FALSE;
}
static VerificationLevel
@@ -618,6 +689,8 @@ verify_identity (GoaKerberosIdentity *self,
krb5_cc_cursor cursor;
krb5_creds credentials;
krb5_error_code error_code;
+ krb5_timestamp start_time = 0;
+ krb5_timestamp renewal_time = 0;
krb5_timestamp expiration_time = 0;
VerificationLevel verification_level = VERIFICATION_LEVEL_UNVERIFIED;
@@ -669,7 +742,15 @@ verify_identity (GoaKerberosIdentity *self,
{
if (credentials_validate_existence (self, principal, &credentials))
{
- if (!credentials_are_expired (self, &credentials, &expiration_time))
+ gboolean credentials_are_expired = TRUE;
+
+ examine_credentials (self, &credentials,
+ &start_time,
+ &renewal_time,
+ &expiration_time,
+ &credentials_are_expired);
+
+ if (!credentials_are_expired)
verification_level = VERIFICATION_LEVEL_SIGNED_IN;
else
verification_level = VERIFICATION_LEVEL_EXISTS;
@@ -720,6 +801,8 @@ verify_identity (GoaKerberosIdentity *self,
out:
G_LOCK (identity_lock);
+ set_start_time (self, start_time);
+ set_renewal_time (self, renewal_time);
set_expiration_time (self, expiration_time);
G_UNLOCK (identity_lock);
@@ -894,14 +977,17 @@ disconnect_alarm_signals (GoaKerberosIdentity *self)
static void
connect_alarm_signals (GoaKerberosIdentity *self)
{
- g_signal_connect (G_OBJECT (self->priv->renewal_alarm),
- "fired",
- G_CALLBACK (on_renewal_alarm_fired),
- self);
- g_signal_connect (G_OBJECT (self->priv->renewal_alarm),
- "rearmed",
- G_CALLBACK (on_renewal_alarm_rearmed),
- self);
+ if (self->priv->renewal_alarm)
+ {
+ g_signal_connect (G_OBJECT (self->priv->renewal_alarm),
+ "fired",
+ G_CALLBACK (on_renewal_alarm_fired),
+ self);
+ g_signal_connect (G_OBJECT (self->priv->renewal_alarm),
+ "rearmed",
+ G_CALLBACK (on_renewal_alarm_rearmed),
+ self);
+ }
g_signal_connect (G_OBJECT (self->priv->expiring_alarm),
"fired",
G_CALLBACK (on_expiring_alarm_fired),
@@ -923,37 +1009,48 @@ connect_alarm_signals (GoaKerberosIdentity *self)
static void
reset_alarms (GoaKerberosIdentity *self)
{
- GDateTime *now;
- GDateTime *expiration_time;
- GDateTime *expiring_time;
- GDateTime *renewal_time;
- GTimeSpan time_span_until_expiration;
+ GDateTime *start_time = NULL;
+ GDateTime *expiration_time = NULL;
+ GDateTime *expiring_time = NULL;
+ GDateTime *latest_possible_renewal_time = NULL;
+ GDateTime *renewal_time = NULL;
- now = g_date_time_new_now_local ();
G_LOCK (identity_lock);
+ start_time = g_date_time_new_from_unix_local (self->priv->start_time);
+ if (self->priv->renewal_time != 0)
+ latest_possible_renewal_time = g_date_time_new_from_unix_local (self->priv->renewal_time);
expiration_time = g_date_time_new_from_unix_local (self->priv->expiration_time);
G_UNLOCK (identity_lock);
- time_span_until_expiration = g_date_time_difference (expiration_time, now);
- g_date_time_unref (now);
/* Let the user reauthenticate 10 min before expiration */
expiring_time = g_date_time_add_minutes (expiration_time, -10);
- /* Try to quietly auto-renew halfway through so in ideal configurations
- * the ticket is never more than halfway to expired
- */
- renewal_time = g_date_time_add (expiration_time,
- -(time_span_until_expiration / 2));
+ if (latest_possible_renewal_time != NULL)
+ {
+ GTimeSpan lifespan;
+
+ lifespan = g_date_time_difference (expiration_time, start_time);
+
+ /* Try to quietly auto-renew halfway through so in ideal configurations
+ * the ticket is never more than halfway to unrenewable
+ */
+ renewal_time = g_date_time_add (start_time, lifespan / 2);
+ }
disconnect_alarm_signals (self);
- reset_alarm (self, &self->priv->renewal_alarm, renewal_time);
+ if (renewal_time != NULL)
+ reset_alarm (self, &self->priv->renewal_alarm, renewal_time);
+
reset_alarm (self, &self->priv->expiring_alarm, expiring_time);
reset_alarm (self, &self->priv->expiration_alarm, expiration_time);
- g_date_time_unref (renewal_time);
- g_date_time_unref (expiring_time);
- g_date_time_unref (expiration_time);
+ g_clear_pointer (&expiring_time, g_date_time_unref);
+ g_clear_pointer (&renewal_time, g_date_time_unref);
+ g_clear_pointer (&expiration_time, g_date_time_unref);
+ g_clear_pointer (&latest_possible_renewal_time, g_date_time_unref);
+ g_clear_pointer (&start_time, g_date_time_unref);
+
connect_alarm_signals (self);
}
@@ -1376,6 +1473,8 @@ goa_kerberos_identity_update (GoaKerberosIdentity *self,
G_LOCK (identity_lock);
update_identifier (self, new_identity);
+ time_changed |= set_start_time (self, new_identity->priv->start_time);
+ time_changed |= set_renewal_time (self, new_identity->priv->renewal_time);
time_changed |= set_expiration_time (self, new_identity->priv->expiration_time);
old_verification_level = self->priv->cached_verification_level;
new_verification_level = new_identity->priv->cached_verification_level;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]