Пример #1
0
/*
 * 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;
}
Пример #2
0
/* 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;
}
Пример #3
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;
}
Пример #4
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);
    }
}
Пример #5
0
/*
 * 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;
}
Пример #6
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;
}
Пример #7
0
/* 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;
}