/* * Effects: * Destroys the contents of id. id is invalid after call. * * Errors: * system errors (locks related) */ krb5_error_code KRB5_CALLCONV krb5_mcc_destroy(krb5_context context, krb5_ccache id) { krb5_mcc_list_node **curr, *node; krb5_mcc_data *d; k5_cc_mutex_lock(context, &krb5int_mcc_mutex); d = (krb5_mcc_data *)id->data; for (curr = &mcc_head; *curr; curr = &(*curr)->next) { if ((*curr)->cache == d) { node = *curr; *curr = node->next; free(node); break; } } k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); k5_cc_mutex_lock(context, &d->lock); krb5_mcc_free(context, id); free(d->name); k5_cc_mutex_unlock(context, &d->lock); k5_cc_mutex_destroy(&d->lock); free(d); free(id); krb5_change_cache (); return KRB5_OK; }
/* Drop the ref count. If it hits zero, remove the entry from the fcc_set list * and free it. */ static krb5_error_code dereference(krb5_context context, fcc_data *data) { struct fcc_set **fccsp, *temp; k5_cc_mutex_lock(context, &krb5int_cc_file_mutex); for (fccsp = &fccs; *fccsp != NULL; fccsp = &(*fccsp)->next) { if ((*fccsp)->data == data) break; } assert(*fccsp != NULL); assert((*fccsp)->data == data); (*fccsp)->refcount--; if ((*fccsp)->refcount == 0) { data = (*fccsp)->data; temp = *fccsp; *fccsp = (*fccsp)->next; free(temp); k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); k5_cc_mutex_assert_unlocked(context, &data->lock); free(data->filename); zap(data->buf, sizeof(data->buf)); if (data->fd >= 0) { k5_cc_mutex_lock(context, &data->lock); close_cache_file(context, data); k5_cc_mutex_unlock(context, &data->lock); } k5_cc_mutex_destroy(&data->lock); free(data); } else { k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); } return 0; }
/* Utility routine: Creates the back-end data for a memory cache, and threads it into the global linked list. Call with the global list lock held. */ static krb5_error_code new_mcc_data (const char *name, krb5_mcc_data **dataptr) { krb5_error_code err; krb5_mcc_data *d; krb5_mcc_list_node *n; d = malloc(sizeof(krb5_mcc_data)); if (d == NULL) return KRB5_CC_NOMEM; err = k5_cc_mutex_init(&d->lock); if (err) { free(d); return err; } d->name = strdup(name); if (d->name == NULL) { k5_cc_mutex_destroy(&d->lock); free(d); return KRB5_CC_NOMEM; } d->link = NULL; d->prin = NULL; d->changetime = 0; d->time_offset = 0; d->usec_offset = 0; update_mcc_change_time(d); n = malloc(sizeof(krb5_mcc_list_node)); if (n == NULL) { free(d->name); k5_cc_mutex_destroy(&d->lock); free(d); return KRB5_CC_NOMEM; } n->cache = d; n->next = mcc_head; mcc_head = n; *dataptr = d; return 0; }
void krb5int_cc_finalize(void) { struct krb5_cc_typelist *t, *t_next; k5_cccol_force_unlock(); k5_cc_mutex_destroy(&cccol_lock); k5_mutex_destroy(&cc_typelist_lock); #ifndef NO_FILE_CCACHE k5_cc_mutex_destroy(&krb5int_cc_file_mutex); #endif k5_cc_mutex_destroy(&krb5int_mcc_mutex); #ifdef USE_KEYRING_CCACHE k5_cc_mutex_destroy(&krb5int_krcc_mutex); #endif for (t = cc_typehead; t != INITIAL_TYPEHEAD; t = t_next) { t_next = t->next; free(t); } }
/* * Utility routine: Creates the back-end data for a memory cache, and adds it * to the global table. Give the new object two references, one for the table * slot and one for the caller's handle. * * Call with the global table lock held. */ static krb5_error_code new_mcc_data (const char *name, krb5_mcc_data **dataptr) { krb5_error_code err; krb5_mcc_data *d; d = malloc(sizeof(krb5_mcc_data)); if (d == NULL) return KRB5_CC_NOMEM; err = k5_cc_mutex_init(&d->lock); if (err) { free(d); return err; } d->name = strdup(name); if (d->name == NULL) { k5_cc_mutex_destroy(&d->lock); free(d); return KRB5_CC_NOMEM; } d->link = NULL; d->prin = NULL; d->time_offset = 0; d->usec_offset = 0; d->refcount = 2; d->generation = 0; if (k5_hashtab_add(mcc_hashtab, d->name, strlen(d->name), d) != 0) { free(d->name); k5_cc_mutex_destroy(&d->lock); free(d); return KRB5_CC_NOMEM; } *dataptr = d; return 0; }
/* * Modifies: * id * * Effects: * Invalidates the id, and frees any resources associated with accessing * the cache. */ krb5_error_code KRB5_CALLCONV krb5_mcc_close(krb5_context context, krb5_ccache id) { krb5_mcc_data *d = id->data; int count; free(id); k5_cc_mutex_lock(context, &d->lock); count = --d->refcount; k5_cc_mutex_unlock(context, &d->lock); if (count == 0) { /* This is the last active handle referencing d and d has been removed * from the table, so we can release it. */ empty_mcc_cache(context, d); free(d->name); k5_cc_mutex_destroy(&d->lock); free(d); } return KRB5_OK; }
/* Create a file ccache handle for the pathname given by residual. */ static krb5_error_code KRB5_CALLCONV fcc_resolve(krb5_context context, krb5_ccache *id, const char *residual) { krb5_ccache lid; krb5_error_code ret; fcc_data *data; struct fcc_set *setptr; k5_cc_mutex_lock(context, &krb5int_cc_file_mutex); for (setptr = fccs; setptr; setptr = setptr->next) { if (!strcmp(setptr->data->filename, residual)) break; } if (setptr) { data = setptr->data; assert(setptr->refcount != 0); setptr->refcount++; assert(setptr->refcount != 0); k5_cc_mutex_lock(context, &data->lock); k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); } else { data = malloc(sizeof(fcc_data)); if (data == NULL) { k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); return KRB5_CC_NOMEM; } data->filename = strdup(residual); if (data->filename == NULL) { k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); free(data); return KRB5_CC_NOMEM; } ret = k5_cc_mutex_init(&data->lock); if (ret) { k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); free(data->filename); free(data); return ret; } k5_cc_mutex_lock(context, &data->lock); /* data->version,mode filled in for real later */ data->version = data->mode = 0; data->flags = KRB5_TC_OPENCLOSE; data->fd = -1; data->valid_bytes = 0; setptr = malloc(sizeof(struct fcc_set)); if (setptr == NULL) { k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); k5_cc_mutex_unlock(context, &data->lock); k5_cc_mutex_destroy(&data->lock); free(data->filename); free(data); return KRB5_CC_NOMEM; } setptr->refcount = 1; setptr->data = data; setptr->next = fccs; fccs = setptr; k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); } k5_cc_mutex_assert_locked(context, &data->lock); k5_cc_mutex_unlock(context, &data->lock); lid = malloc(sizeof(struct _krb5_ccache)); if (lid == NULL) { dereference(context, data); return KRB5_CC_NOMEM; } lid->ops = &krb5_fcc_ops; lid->data = data; lid->magic = KV5M_CCACHE; /* Other routines will get errors on open, and callers must expect them, if * cache is non-existent/unusable. */ *id = lid; return 0; }