krb5_mcache *m, *m_c;
size_t counter = 0;
int ret = 0;
+ unsigned create_anonymous = 0;
*out = NULL;
ALLOC(m, 1);
free(m);
return EAGAIN; /* XXX */
}
- if(name == NULL)
+ if(name == NULL) {
ret = asprintf(&m->name, "u%p-%llu", m, (unsigned long long)counter);
- else
+ } else if (strcmp(name, "anonymous") == 0) {
+ ret = asprintf(&m->name, "anonymous-%p-%llu", m, (unsigned long long)counter);
+ create_anonymous = 1;
+ } else {
m->name = strdup(name);
+ }
if(ret < 0 || m->name == NULL) {
free(m);
return krb5_enomem(context);
}
- if (strcmp(m->name, "anonymous") == 0) {
- HEIMDAL_MUTEX_init(&(m->mutex));
- m->anonymous = 1;
- m->dead = 0;
- m->refcnt = 1;
- m->primary_principal = NULL;
- m->creds = NULL;
- m->mtime = time(NULL);
- m->kdc_offset = 0;
- m->next = NULL;
- *out = m;
- return 0;
- }
/* check for dups first */
HEIMDAL_MUTEX_lock(&mcc_mutex);
if (strcmp(m->name, m_c->name) == 0)
break;
if (m_c) {
- if (name) {
+ if (name && !create_anonymous) {
/* We raced with another thread to create this cache */
free(m->name);
free(m);
return 0;
}
- m->anonymous = 0;
+ m->anonymous = create_anonymous;
m->dead = 0;
m->refcnt = 1;
m->primary_principal = NULL;
{
krb5_mcache **n, *m = MCACHE(id);
- if (m->anonymous) {
- HEIMDAL_MUTEX_lock(&(m->mutex));
- if (m->refcnt == 0) {
- HEIMDAL_MUTEX_unlock(&(m->mutex));
- krb5_abortx(context, "mcc_destroy: refcnt already 0");
- }
- if (!MISDEAD(m))
- mcc_destroy_internal(context, m);
- HEIMDAL_MUTEX_unlock(&(m->mutex));
- return 0;
- }
-
HEIMDAL_MUTEX_lock(&mcc_mutex);
HEIMDAL_MUTEX_lock(&(m->mutex));
if (m->refcnt == 0)
krb5_mcache *cache;
};
+static krb5_mcache *
+mcc_get_cache_find_next_internal(krb5_mcache *next)
+{
+ HEIMDAL_MUTEX_lock(&mcc_mutex);
+ for (; next != NULL && next->anonymous; next = next->next) {
+ /* noop: iterate over all anonymous entries */
+ }
+ if (next != NULL) {
+ HEIMDAL_MUTEX_lock(&(next->mutex));
+ next->refcnt++;
+ HEIMDAL_MUTEX_unlock(&(next->mutex));
+ next = next->next;
+ }
+ HEIMDAL_MUTEX_unlock(&mcc_mutex);
+
+ return next;
+}
+
static krb5_error_code KRB5_CALLCONV
mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
{
if (iter == NULL)
return krb5_enomem(context);
- HEIMDAL_MUTEX_lock(&mcc_mutex);
- iter->cache = mcc_head;
- if (iter->cache) {
- HEIMDAL_MUTEX_lock(&(iter->cache->mutex));
- iter->cache->refcnt++;
- HEIMDAL_MUTEX_unlock(&(iter->cache->mutex));
- }
- HEIMDAL_MUTEX_unlock(&mcc_mutex);
+ iter->cache = mcc_get_cache_find_next_internal(mcc_head);
*cursor = iter;
return 0;
if (iter->cache == NULL)
return KRB5_CC_END;
- HEIMDAL_MUTEX_lock(&mcc_mutex);
m = iter->cache;
- if (m->next)
- {
- HEIMDAL_MUTEX_lock(&(m->next->mutex));
- m->next->refcnt++;
- HEIMDAL_MUTEX_unlock(&(m->next->mutex));
- }
-
- iter->cache = m->next;
- HEIMDAL_MUTEX_unlock(&mcc_mutex);
+ iter->cache = mcc_get_cache_find_next_internal(m);
ret = _krb5_cc_allocate(context, &krb5_mcc_ops, id);
if (ret)