From 25a3cc4de532748e162ad84451407e3263f8d512 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 22 Sep 2015 14:33:35 -0400
Subject: [PATCH 1/2] identity: consider ticket start time when calculating
renewal time
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.
---
src/goaidentity/goaidentity.c | 7 +++++
src/goaidentity/goakerberosidentity.c | 55 +++++++++++++++++++++++++++++------
2 files changed, 53 insertions(+), 9 deletions(-)
diff --git a/src/goaidentity/goaidentity.c b/src/goaidentity/goaidentity.c
index 2fc491be2876..2904e2afe020 100644
--- a/src/goaidentity/goaidentity.c
+++ b/src/goaidentity/goaidentity.c
@@ -40,6 +40,13 @@ 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 ("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 1ce5079b6194..f43978d49ebf 100644
--- a/src/goaidentity/goakerberosidentity.c
+++ b/src/goaidentity/goakerberosidentity.c
@@ -49,6 +49,8 @@ struct _GoaKerberosIdentityPrivate
char *preauth_identity_source;
+ krb5_timestamp start_time;
+ guint start_time_idle_id;
krb5_timestamp expiration_time;
guint expiration_time_idle_id;
@@ -75,6 +77,7 @@ enum
PROP_0,
PROP_IDENTIFIER,
PROP_IS_SIGNED_IN,
+ PROP_START_TIMESTAMP,
PROP_EXPIRATION_TIMESTAMP
};
@@ -148,6 +151,11 @@ 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_EXPIRATION_TIMESTAMP:
G_LOCK (identity_lock);
g_value_set_int64 (value, (gint64) self->priv->expiration_time);
@@ -221,6 +229,9 @@ 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_EXPIRATION_TIMESTAMP,
"expiration-timestamp");
@@ -573,6 +584,23 @@ queue_notify (GoaKerberosIdentity *self,
}
static void
+set_start_time (GoaKerberosIdentity *self,
+ krb5_timestamp start_time)
+{
+ G_LOCK (identity_lock);
+ if (self->priv->start_time != start_time)
+ {
+ self->priv->start_time = start_time;
+ G_UNLOCK (identity_lock);
+ queue_notify (self,
+ &self->priv->start_time_idle_id,
+ "start-timestamp");
+ G_LOCK (identity_lock);
+ }
+ G_UNLOCK (identity_lock);
+}
+
+static void
set_expiration_time (GoaKerberosIdentity *self,
krb5_timestamp expiration_time)
{
@@ -592,6 +620,7 @@ set_expiration_time (GoaKerberosIdentity *self,
static gboolean
credentials_are_expired (GoaKerberosIdentity *self,
krb5_creds *credentials,
+ krb5_timestamp *start_time,
krb5_timestamp *expiration_time)
{
krb5_timestamp current_time;
@@ -599,11 +628,17 @@ credentials_are_expired (GoaKerberosIdentity *self,
current_time = get_current_time (self);
G_LOCK (identity_lock);
+ if (self->priv->start_time == 0)
+ *start_time = credentials->times.starttime;
+ else
+ *start_time = MIN (self->priv->start_time,
+ credentials->times.starttime);
*expiration_time = MAX (credentials->times.endtime,
self->priv->expiration_time);
G_UNLOCK (identity_lock);
- if (credentials->times.endtime <= current_time)
+ if (current_time < credentials->times.starttime ||
+ credentials->times.endtime <= current_time)
{
return TRUE;
}
@@ -620,6 +655,7 @@ verify_identity (GoaKerberosIdentity *self,
krb5_cc_cursor cursor;
krb5_creds credentials;
krb5_error_code error_code;
+ krb5_timestamp start_time = 0;
krb5_timestamp expiration_time = 0;
VerificationLevel verification_level = VERIFICATION_LEVEL_UNVERIFIED;
@@ -671,7 +707,7 @@ verify_identity (GoaKerberosIdentity *self,
{
if (credentials_validate_existence (self, principal, &credentials))
{
- if (!credentials_are_expired (self, &credentials, &expiration_time))
+ if (!credentials_are_expired (self, &credentials, &start_time, &expiration_time))
verification_level = VERIFICATION_LEVEL_SIGNED_IN;
else
verification_level = VERIFICATION_LEVEL_EXISTS;
@@ -720,6 +756,7 @@ verify_identity (GoaKerberosIdentity *self,
goto out;
}
out:
+ set_start_time (self, start_time);
set_expiration_time (self, expiration_time);
if (principal != NULL)
@@ -922,18 +959,18 @@ connect_alarm_signals (GoaKerberosIdentity *self)
static void
reset_alarms (GoaKerberosIdentity *self)
{
- GDateTime *now;
+ GDateTime *start_time;
GDateTime *expiration_time;
GDateTime *expiring_time;
GDateTime *renewal_time;
- GTimeSpan time_span_until_expiration;
+ GTimeSpan lifespan;
- now = g_date_time_new_now_local ();
G_LOCK (identity_lock);
+ start_time = g_date_time_new_from_unix_local (self->priv->start_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);
+
+ lifespan = g_date_time_difference (expiration_time, start_time);
/* Let the user reauthenticate 10 min before expiration */
expiring_time = g_date_time_add_minutes (expiration_time, -10);
@@ -941,8 +978,7 @@ reset_alarms (GoaKerberosIdentity *self)
/* 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));
+ renewal_time = g_date_time_add (expiration_time, -(lifespan / 2));
disconnect_alarm_signals (self);
@@ -952,6 +988,7 @@ reset_alarms (GoaKerberosIdentity *self)
g_date_time_unref (renewal_time);
g_date_time_unref (expiring_time);
+ g_date_time_unref (start_time);
g_date_time_unref (expiration_time);
connect_alarm_signals (self);
}
--
2.5.0
From d3f7bcc56592a3113c1cde55bf67c44514acc7f9 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 22 Sep 2015 14:38:29 -0400
Subject: [PATCH 2/2] identity: don't ignore almost all renewal requests
There's a bug in the code where we ignore all renewal requests for
objects we already know about.
This means we'll only ever honor renewal requests that happen almost
immediately after start up.
This commit fixes the bug, so the only renewal requests that aren't
honored, are those that have been specifically disabled by the user.
This was clearly the original intention of the buggy code.
---
src/goaidentity/goaidentityservice.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/goaidentity/goaidentityservice.c b/src/goaidentity/goaidentityservice.c
index 6b6225adbc61..bb5d3a7dbe25 100644
--- a/src/goaidentity/goaidentityservice.c
+++ b/src/goaidentity/goaidentityservice.c
@@ -741,16 +741,17 @@ on_identity_needs_renewal (GoaIdentityManager *identity_manager,
principal = goa_identity_get_identifier (identity);
- g_debug ("GoaIdentityService: identity %s needs renewal", principal);
-
object = find_object_with_principal (self, principal, TRUE);
- if (object != NULL)
+ if (object != NULL && should_ignore_object (self, object))
{
- should_ignore_object (self, object);
+ g_debug ("GoaIdentityService: ignoring identity %s that says it needs renewal", principal);
+
return;
}
+ g_debug ("GoaIdentityService: identity %s needs renewal", principal);
+
goa_identity_manager_renew_identity (GOA_IDENTITY_MANAGER
(self->priv->identity_manager),
identity,
--
2.5.0