1c19800e8SDoug Rabson /* 2c19800e8SDoug Rabson * Copyright (c) 2005, PADL Software Pty Ltd. 3c19800e8SDoug Rabson * All rights reserved. 4c19800e8SDoug Rabson * 5c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without 6c19800e8SDoug Rabson * modification, are permitted provided that the following conditions 7c19800e8SDoug Rabson * are met: 8c19800e8SDoug Rabson * 9c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright 10c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer. 11c19800e8SDoug Rabson * 12c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 13c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the 14c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution. 15c19800e8SDoug Rabson * 16c19800e8SDoug Rabson * 3. Neither the name of PADL Software nor the names of its contributors 17c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software 18c19800e8SDoug Rabson * without specific prior written permission. 19c19800e8SDoug Rabson * 20c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 21c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 24c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30c19800e8SDoug Rabson * SUCH DAMAGE. 31c19800e8SDoug Rabson */ 32c19800e8SDoug Rabson 33c19800e8SDoug Rabson #include "kcm_locl.h" 34c19800e8SDoug Rabson 35*ae771770SStanislav Sedov RCSID("$Id$"); 36c19800e8SDoug Rabson 37c19800e8SDoug Rabson /* thread-safe in case we multi-thread later */ 38c19800e8SDoug Rabson static HEIMDAL_MUTEX events_mutex = HEIMDAL_MUTEX_INITIALIZER; 39c19800e8SDoug Rabson static kcm_event *events_head = NULL; 40c19800e8SDoug Rabson static time_t last_run = 0; 41c19800e8SDoug Rabson 42c19800e8SDoug Rabson static char *action_strings[] = { 43c19800e8SDoug Rabson "NONE", "ACQUIRE_CREDS", "RENEW_CREDS", 44c19800e8SDoug Rabson "DESTROY_CREDS", "DESTROY_EMPTY_CACHE" }; 45c19800e8SDoug Rabson 46c19800e8SDoug Rabson krb5_error_code 47c19800e8SDoug Rabson kcm_enqueue_event(krb5_context context, 48c19800e8SDoug Rabson kcm_event *event) 49c19800e8SDoug Rabson { 50c19800e8SDoug Rabson krb5_error_code ret; 51c19800e8SDoug Rabson 52c19800e8SDoug Rabson if (event->action == KCM_EVENT_NONE) { 53c19800e8SDoug Rabson return 0; 54c19800e8SDoug Rabson } 55c19800e8SDoug Rabson 56c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&events_mutex); 57c19800e8SDoug Rabson ret = kcm_enqueue_event_internal(context, event); 58c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&events_mutex); 59c19800e8SDoug Rabson 60c19800e8SDoug Rabson return ret; 61c19800e8SDoug Rabson } 62c19800e8SDoug Rabson 63c19800e8SDoug Rabson static void 64c19800e8SDoug Rabson print_times(time_t time, char buf[64]) 65c19800e8SDoug Rabson { 66c19800e8SDoug Rabson if (time) 67c19800e8SDoug Rabson strftime(buf, 64, "%m-%dT%H:%M", gmtime(&time)); 68c19800e8SDoug Rabson else 69c19800e8SDoug Rabson strlcpy(buf, "never", 64); 70c19800e8SDoug Rabson } 71c19800e8SDoug Rabson 72c19800e8SDoug Rabson static void 73c19800e8SDoug Rabson log_event(kcm_event *event, char *msg) 74c19800e8SDoug Rabson { 75c19800e8SDoug Rabson char fire_time[64], expire_time[64]; 76c19800e8SDoug Rabson 77c19800e8SDoug Rabson print_times(event->fire_time, fire_time); 78c19800e8SDoug Rabson print_times(event->expire_time, expire_time); 79c19800e8SDoug Rabson 80c19800e8SDoug Rabson kcm_log(7, "%s event %08x: fire_time %s fire_count %d expire_time %s " 81c19800e8SDoug Rabson "backoff_time %d action %s cache %s", 82c19800e8SDoug Rabson msg, event, fire_time, event->fire_count, expire_time, 83c19800e8SDoug Rabson event->backoff_time, action_strings[event->action], 84c19800e8SDoug Rabson event->ccache->name); 85c19800e8SDoug Rabson } 86c19800e8SDoug Rabson 87c19800e8SDoug Rabson krb5_error_code 88c19800e8SDoug Rabson kcm_enqueue_event_internal(krb5_context context, 89c19800e8SDoug Rabson kcm_event *event) 90c19800e8SDoug Rabson { 91c19800e8SDoug Rabson kcm_event **e; 92c19800e8SDoug Rabson 93c19800e8SDoug Rabson if (event->action == KCM_EVENT_NONE) 94c19800e8SDoug Rabson return 0; 95c19800e8SDoug Rabson 96c19800e8SDoug Rabson for (e = &events_head; *e != NULL; e = &(*e)->next) 97c19800e8SDoug Rabson ; 98c19800e8SDoug Rabson 99c19800e8SDoug Rabson *e = (kcm_event *)malloc(sizeof(kcm_event)); 100c19800e8SDoug Rabson if (*e == NULL) { 101c19800e8SDoug Rabson return KRB5_CC_NOMEM; 102c19800e8SDoug Rabson } 103c19800e8SDoug Rabson 104c19800e8SDoug Rabson (*e)->valid = 1; 105c19800e8SDoug Rabson (*e)->fire_time = event->fire_time; 106c19800e8SDoug Rabson (*e)->fire_count = 0; 107c19800e8SDoug Rabson (*e)->expire_time = event->expire_time; 108c19800e8SDoug Rabson (*e)->backoff_time = event->backoff_time; 109c19800e8SDoug Rabson 110c19800e8SDoug Rabson (*e)->action = event->action; 111c19800e8SDoug Rabson 112c19800e8SDoug Rabson kcm_retain_ccache(context, event->ccache); 113c19800e8SDoug Rabson (*e)->ccache = event->ccache; 114c19800e8SDoug Rabson (*e)->next = NULL; 115c19800e8SDoug Rabson 116c19800e8SDoug Rabson log_event(*e, "enqueuing"); 117c19800e8SDoug Rabson 118c19800e8SDoug Rabson return 0; 119c19800e8SDoug Rabson } 120c19800e8SDoug Rabson 121c19800e8SDoug Rabson /* 122c19800e8SDoug Rabson * Dump events list on SIGUSR2 123c19800e8SDoug Rabson */ 124c19800e8SDoug Rabson krb5_error_code 125c19800e8SDoug Rabson kcm_debug_events(krb5_context context) 126c19800e8SDoug Rabson { 127c19800e8SDoug Rabson kcm_event *e; 128c19800e8SDoug Rabson 129c19800e8SDoug Rabson for (e = events_head; e != NULL; e = e->next) 130c19800e8SDoug Rabson log_event(e, "debug"); 131c19800e8SDoug Rabson 132c19800e8SDoug Rabson return 0; 133c19800e8SDoug Rabson } 134c19800e8SDoug Rabson 135c19800e8SDoug Rabson krb5_error_code 136c19800e8SDoug Rabson kcm_enqueue_event_relative(krb5_context context, 137c19800e8SDoug Rabson kcm_event *event) 138c19800e8SDoug Rabson { 139c19800e8SDoug Rabson krb5_error_code ret; 140c19800e8SDoug Rabson kcm_event e; 141c19800e8SDoug Rabson 142c19800e8SDoug Rabson e = *event; 143c19800e8SDoug Rabson e.backoff_time = e.fire_time; 144c19800e8SDoug Rabson e.fire_time += time(NULL); 145c19800e8SDoug Rabson 146c19800e8SDoug Rabson ret = kcm_enqueue_event(context, &e); 147c19800e8SDoug Rabson 148c19800e8SDoug Rabson return ret; 149c19800e8SDoug Rabson } 150c19800e8SDoug Rabson 151c19800e8SDoug Rabson static krb5_error_code 152c19800e8SDoug Rabson kcm_remove_event_internal(krb5_context context, 153c19800e8SDoug Rabson kcm_event **e) 154c19800e8SDoug Rabson { 155c19800e8SDoug Rabson kcm_event *next; 156c19800e8SDoug Rabson 157c19800e8SDoug Rabson next = (*e)->next; 158c19800e8SDoug Rabson 159c19800e8SDoug Rabson (*e)->valid = 0; 160c19800e8SDoug Rabson (*e)->fire_time = 0; 161c19800e8SDoug Rabson (*e)->fire_count = 0; 162c19800e8SDoug Rabson (*e)->expire_time = 0; 163c19800e8SDoug Rabson (*e)->backoff_time = 0; 164*ae771770SStanislav Sedov kcm_release_ccache(context, (*e)->ccache); 165c19800e8SDoug Rabson (*e)->next = NULL; 166c19800e8SDoug Rabson free(*e); 167c19800e8SDoug Rabson 168c19800e8SDoug Rabson *e = next; 169c19800e8SDoug Rabson 170c19800e8SDoug Rabson return 0; 171c19800e8SDoug Rabson } 172c19800e8SDoug Rabson 173c19800e8SDoug Rabson static int 174c19800e8SDoug Rabson is_primary_credential_p(krb5_context context, 175c19800e8SDoug Rabson kcm_ccache ccache, 176c19800e8SDoug Rabson krb5_creds *newcred) 177c19800e8SDoug Rabson { 178c19800e8SDoug Rabson krb5_flags whichfields; 179c19800e8SDoug Rabson 180c19800e8SDoug Rabson if (ccache->client == NULL) 181c19800e8SDoug Rabson return 0; 182c19800e8SDoug Rabson 183c19800e8SDoug Rabson if (newcred->client == NULL || 184c19800e8SDoug Rabson !krb5_principal_compare(context, ccache->client, newcred->client)) 185c19800e8SDoug Rabson return 0; 186c19800e8SDoug Rabson 187c19800e8SDoug Rabson /* XXX just checks whether it's the first credential in the cache */ 188c19800e8SDoug Rabson if (ccache->creds == NULL) 189c19800e8SDoug Rabson return 0; 190c19800e8SDoug Rabson 191c19800e8SDoug Rabson whichfields = KRB5_TC_MATCH_KEYTYPE | KRB5_TC_MATCH_FLAGS_EXACT | 192c19800e8SDoug Rabson KRB5_TC_MATCH_TIMES_EXACT | KRB5_TC_MATCH_AUTHDATA | 193c19800e8SDoug Rabson KRB5_TC_MATCH_2ND_TKT | KRB5_TC_MATCH_IS_SKEY; 194c19800e8SDoug Rabson 195c19800e8SDoug Rabson return krb5_compare_creds(context, whichfields, newcred, &ccache->creds->cred); 196c19800e8SDoug Rabson } 197c19800e8SDoug Rabson 198c19800e8SDoug Rabson /* 199c19800e8SDoug Rabson * Setup default events for a new credential 200c19800e8SDoug Rabson */ 201c19800e8SDoug Rabson static krb5_error_code 202c19800e8SDoug Rabson kcm_ccache_make_default_event(krb5_context context, 203c19800e8SDoug Rabson kcm_event *event, 204c19800e8SDoug Rabson krb5_creds *newcred) 205c19800e8SDoug Rabson { 206c19800e8SDoug Rabson krb5_error_code ret = 0; 207c19800e8SDoug Rabson kcm_ccache ccache = event->ccache; 208c19800e8SDoug Rabson 209c19800e8SDoug Rabson event->fire_time = 0; 210c19800e8SDoug Rabson event->expire_time = 0; 211c19800e8SDoug Rabson event->backoff_time = KCM_EVENT_DEFAULT_BACKOFF_TIME; 212c19800e8SDoug Rabson 213c19800e8SDoug Rabson if (newcred == NULL) { 214c19800e8SDoug Rabson /* no creds, must be acquire creds request */ 215c19800e8SDoug Rabson if ((ccache->flags & KCM_MASK_KEY_PRESENT) == 0) { 216c19800e8SDoug Rabson kcm_log(0, "Cannot acquire credentials without a key"); 217c19800e8SDoug Rabson return KRB5_FCC_INTERNAL; 218c19800e8SDoug Rabson } 219c19800e8SDoug Rabson 220c19800e8SDoug Rabson event->fire_time = time(NULL); /* right away */ 221c19800e8SDoug Rabson event->action = KCM_EVENT_ACQUIRE_CREDS; 222c19800e8SDoug Rabson } else if (is_primary_credential_p(context, ccache, newcred)) { 223c19800e8SDoug Rabson if (newcred->flags.b.renewable) { 224c19800e8SDoug Rabson event->action = KCM_EVENT_RENEW_CREDS; 225c19800e8SDoug Rabson ccache->flags |= KCM_FLAGS_RENEWABLE; 226c19800e8SDoug Rabson } else { 227c19800e8SDoug Rabson if (ccache->flags & KCM_MASK_KEY_PRESENT) 228c19800e8SDoug Rabson event->action = KCM_EVENT_ACQUIRE_CREDS; 229c19800e8SDoug Rabson else 230c19800e8SDoug Rabson event->action = KCM_EVENT_NONE; 231c19800e8SDoug Rabson ccache->flags &= ~(KCM_FLAGS_RENEWABLE); 232c19800e8SDoug Rabson } 233c19800e8SDoug Rabson /* requeue with some slop factor */ 234c19800e8SDoug Rabson event->fire_time = newcred->times.endtime - KCM_EVENT_QUEUE_INTERVAL; 235c19800e8SDoug Rabson } else { 236c19800e8SDoug Rabson event->action = KCM_EVENT_NONE; 237c19800e8SDoug Rabson } 238c19800e8SDoug Rabson 239c19800e8SDoug Rabson return ret; 240c19800e8SDoug Rabson } 241c19800e8SDoug Rabson 242c19800e8SDoug Rabson krb5_error_code 243c19800e8SDoug Rabson kcm_ccache_enqueue_default(krb5_context context, 244c19800e8SDoug Rabson kcm_ccache ccache, 245c19800e8SDoug Rabson krb5_creds *newcred) 246c19800e8SDoug Rabson { 247c19800e8SDoug Rabson kcm_event event; 248c19800e8SDoug Rabson krb5_error_code ret; 249c19800e8SDoug Rabson 250c19800e8SDoug Rabson memset(&event, 0, sizeof(event)); 251c19800e8SDoug Rabson event.ccache = ccache; 252c19800e8SDoug Rabson 253c19800e8SDoug Rabson ret = kcm_ccache_make_default_event(context, &event, newcred); 254c19800e8SDoug Rabson if (ret) 255c19800e8SDoug Rabson return ret; 256c19800e8SDoug Rabson 257c19800e8SDoug Rabson ret = kcm_enqueue_event_internal(context, &event); 258c19800e8SDoug Rabson if (ret) 259c19800e8SDoug Rabson return ret; 260c19800e8SDoug Rabson 261c19800e8SDoug Rabson return 0; 262c19800e8SDoug Rabson } 263c19800e8SDoug Rabson 264c19800e8SDoug Rabson krb5_error_code 265c19800e8SDoug Rabson kcm_remove_event(krb5_context context, 266c19800e8SDoug Rabson kcm_event *event) 267c19800e8SDoug Rabson { 268c19800e8SDoug Rabson krb5_error_code ret; 269c19800e8SDoug Rabson kcm_event **e; 270c19800e8SDoug Rabson int found = 0; 271c19800e8SDoug Rabson 272c19800e8SDoug Rabson log_event(event, "removing"); 273c19800e8SDoug Rabson 274c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&events_mutex); 275c19800e8SDoug Rabson for (e = &events_head; *e != NULL; e = &(*e)->next) { 276c19800e8SDoug Rabson if (event == *e) { 277c19800e8SDoug Rabson *e = event->next; 278c19800e8SDoug Rabson found++; 279c19800e8SDoug Rabson break; 280c19800e8SDoug Rabson } 281c19800e8SDoug Rabson } 282c19800e8SDoug Rabson 283c19800e8SDoug Rabson if (!found) { 284c19800e8SDoug Rabson ret = KRB5_CC_NOTFOUND; 285c19800e8SDoug Rabson goto out; 286c19800e8SDoug Rabson } 287c19800e8SDoug Rabson 288c19800e8SDoug Rabson ret = kcm_remove_event_internal(context, &event); 289c19800e8SDoug Rabson 290c19800e8SDoug Rabson out: 291c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&events_mutex); 292c19800e8SDoug Rabson 293c19800e8SDoug Rabson return ret; 294c19800e8SDoug Rabson } 295c19800e8SDoug Rabson 296c19800e8SDoug Rabson krb5_error_code 297c19800e8SDoug Rabson kcm_cleanup_events(krb5_context context, 298c19800e8SDoug Rabson kcm_ccache ccache) 299c19800e8SDoug Rabson { 300c19800e8SDoug Rabson kcm_event **e; 301c19800e8SDoug Rabson 302c19800e8SDoug Rabson KCM_ASSERT_VALID(ccache); 303c19800e8SDoug Rabson 304c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&events_mutex); 305c19800e8SDoug Rabson 306c19800e8SDoug Rabson for (e = &events_head; *e != NULL; e = &(*e)->next) { 307c19800e8SDoug Rabson if ((*e)->valid && (*e)->ccache == ccache) { 308c19800e8SDoug Rabson kcm_remove_event_internal(context, e); 309c19800e8SDoug Rabson } 310c19800e8SDoug Rabson if (*e == NULL) 311c19800e8SDoug Rabson break; 312c19800e8SDoug Rabson } 313c19800e8SDoug Rabson 314c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&events_mutex); 315c19800e8SDoug Rabson 316c19800e8SDoug Rabson return 0; 317c19800e8SDoug Rabson } 318c19800e8SDoug Rabson 319c19800e8SDoug Rabson static krb5_error_code 320c19800e8SDoug Rabson kcm_fire_event(krb5_context context, 321c19800e8SDoug Rabson kcm_event **e) 322c19800e8SDoug Rabson { 323c19800e8SDoug Rabson kcm_event *event; 324c19800e8SDoug Rabson krb5_error_code ret; 325c19800e8SDoug Rabson krb5_creds *credp = NULL; 326c19800e8SDoug Rabson int oneshot = 1; 327c19800e8SDoug Rabson 328c19800e8SDoug Rabson event = *e; 329c19800e8SDoug Rabson 330c19800e8SDoug Rabson switch (event->action) { 331c19800e8SDoug Rabson case KCM_EVENT_ACQUIRE_CREDS: 332c19800e8SDoug Rabson ret = kcm_ccache_acquire(context, event->ccache, &credp); 333c19800e8SDoug Rabson oneshot = 0; 334c19800e8SDoug Rabson break; 335c19800e8SDoug Rabson case KCM_EVENT_RENEW_CREDS: 336c19800e8SDoug Rabson ret = kcm_ccache_refresh(context, event->ccache, &credp); 337c19800e8SDoug Rabson if (ret == KRB5KRB_AP_ERR_TKT_EXPIRED) { 338c19800e8SDoug Rabson ret = kcm_ccache_acquire(context, event->ccache, &credp); 339c19800e8SDoug Rabson } 340c19800e8SDoug Rabson oneshot = 0; 341c19800e8SDoug Rabson break; 342c19800e8SDoug Rabson case KCM_EVENT_DESTROY_CREDS: 343c19800e8SDoug Rabson ret = kcm_ccache_destroy(context, event->ccache->name); 344c19800e8SDoug Rabson break; 345c19800e8SDoug Rabson case KCM_EVENT_DESTROY_EMPTY_CACHE: 346c19800e8SDoug Rabson ret = kcm_ccache_destroy_if_empty(context, event->ccache); 347c19800e8SDoug Rabson break; 348c19800e8SDoug Rabson default: 349c19800e8SDoug Rabson ret = KRB5_FCC_INTERNAL; 350c19800e8SDoug Rabson break; 351c19800e8SDoug Rabson } 352c19800e8SDoug Rabson 353c19800e8SDoug Rabson event->fire_count++; 354c19800e8SDoug Rabson 355c19800e8SDoug Rabson if (ret) { 356c19800e8SDoug Rabson /* Reschedule failed event for another time */ 357c19800e8SDoug Rabson event->fire_time += event->backoff_time; 358c19800e8SDoug Rabson if (event->backoff_time < KCM_EVENT_MAX_BACKOFF_TIME) 359c19800e8SDoug Rabson event->backoff_time *= 2; 360c19800e8SDoug Rabson 361c19800e8SDoug Rabson /* Remove it if it would never get executed */ 362c19800e8SDoug Rabson if (event->expire_time && 363c19800e8SDoug Rabson event->fire_time > event->expire_time) 364c19800e8SDoug Rabson kcm_remove_event_internal(context, e); 365c19800e8SDoug Rabson } else { 366c19800e8SDoug Rabson if (!oneshot) { 367c19800e8SDoug Rabson char *cpn; 368c19800e8SDoug Rabson 369c19800e8SDoug Rabson if (krb5_unparse_name(context, event->ccache->client, 370c19800e8SDoug Rabson &cpn)) 371c19800e8SDoug Rabson cpn = NULL; 372c19800e8SDoug Rabson 373c19800e8SDoug Rabson kcm_log(0, "%s credentials in cache %s for principal %s", 374c19800e8SDoug Rabson (event->action == KCM_EVENT_ACQUIRE_CREDS) ? 375c19800e8SDoug Rabson "Acquired" : "Renewed", 376c19800e8SDoug Rabson event->ccache->name, 377c19800e8SDoug Rabson (cpn != NULL) ? cpn : "<none>"); 378c19800e8SDoug Rabson 379c19800e8SDoug Rabson if (cpn != NULL) 380c19800e8SDoug Rabson free(cpn); 381c19800e8SDoug Rabson 382c19800e8SDoug Rabson /* Succeeded, but possibly replaced with another event */ 383c19800e8SDoug Rabson ret = kcm_ccache_make_default_event(context, event, credp); 384c19800e8SDoug Rabson if (ret || event->action == KCM_EVENT_NONE) 385c19800e8SDoug Rabson oneshot = 1; 386c19800e8SDoug Rabson else 387c19800e8SDoug Rabson log_event(event, "requeuing"); 388c19800e8SDoug Rabson } 389c19800e8SDoug Rabson if (oneshot) 390c19800e8SDoug Rabson kcm_remove_event_internal(context, e); 391c19800e8SDoug Rabson } 392c19800e8SDoug Rabson 393c19800e8SDoug Rabson return ret; 394c19800e8SDoug Rabson } 395c19800e8SDoug Rabson 396c19800e8SDoug Rabson krb5_error_code 397*ae771770SStanislav Sedov kcm_run_events(krb5_context context, time_t now) 398c19800e8SDoug Rabson { 399c19800e8SDoug Rabson krb5_error_code ret; 400c19800e8SDoug Rabson kcm_event **e; 401c19800e8SDoug Rabson 402c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&events_mutex); 403c19800e8SDoug Rabson 404c19800e8SDoug Rabson /* Only run event queue every N seconds */ 405c19800e8SDoug Rabson if (now < last_run + KCM_EVENT_QUEUE_INTERVAL) { 406c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&events_mutex); 407c19800e8SDoug Rabson return 0; 408c19800e8SDoug Rabson } 409c19800e8SDoug Rabson 410c19800e8SDoug Rabson /* go through events list, fire and expire */ 411c19800e8SDoug Rabson for (e = &events_head; *e != NULL; e = &(*e)->next) { 412c19800e8SDoug Rabson if ((*e)->valid == 0) 413c19800e8SDoug Rabson continue; 414c19800e8SDoug Rabson 415c19800e8SDoug Rabson if (now >= (*e)->fire_time) { 416c19800e8SDoug Rabson ret = kcm_fire_event(context, e); 417c19800e8SDoug Rabson if (ret) { 418c19800e8SDoug Rabson kcm_log(1, "Could not fire event for cache %s: %s", 419c19800e8SDoug Rabson (*e)->ccache->name, krb5_get_err_text(context, ret)); 420c19800e8SDoug Rabson } 421c19800e8SDoug Rabson } else if ((*e)->expire_time && now >= (*e)->expire_time) { 422c19800e8SDoug Rabson ret = kcm_remove_event_internal(context, e); 423c19800e8SDoug Rabson if (ret) { 424c19800e8SDoug Rabson kcm_log(1, "Could not expire event for cache %s: %s", 425c19800e8SDoug Rabson (*e)->ccache->name, krb5_get_err_text(context, ret)); 426c19800e8SDoug Rabson } 427c19800e8SDoug Rabson } 428c19800e8SDoug Rabson 429c19800e8SDoug Rabson if (*e == NULL) 430c19800e8SDoug Rabson break; 431c19800e8SDoug Rabson } 432c19800e8SDoug Rabson 433c19800e8SDoug Rabson last_run = now; 434c19800e8SDoug Rabson 435c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&events_mutex); 436c19800e8SDoug Rabson 437c19800e8SDoug Rabson return 0; 438c19800e8SDoug Rabson } 439c19800e8SDoug Rabson 440