/* * 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; }
/* Create or overwrite the cache file with a header and default principal. */ static krb5_error_code KRB5_CALLCONV fcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) { krb5_error_code ret; fcc_data *data = id->data; int st = 0; k5_cc_mutex_lock(context, &data->lock); MAYBE_OPEN(context, id, FCC_OPEN_AND_ERASE); #if defined(HAVE_FCHMOD) || defined(HAVE_CHMOD) #ifdef HAVE_FCHMOD st = fchmod(data->fd, S_IRUSR | S_IWUSR); #else st = chmod(data->filename, S_IRUSR | S_IWUSR); #endif if (st == -1) { ret = interpret_errno(context, errno); MAYBE_CLOSE(context, id, ret); k5_cc_mutex_unlock(context, &data->lock); return ret; } #endif ret = store_principal(context, id, princ); MAYBE_CLOSE(context, id, ret); k5_cc_mutex_unlock(context, &data->lock); krb5_change_cache(); return ret; }
/* * Modifies: * id * * Effects: * Creates/refreshes the memory cred cache id. If the cache exists, its * contents are destroyed. * * Errors: * system errors */ krb5_error_code KRB5_CALLCONV krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) { krb5_os_context os_ctx = &context->os_context; krb5_error_code ret; krb5_mcc_data *d; d = (krb5_mcc_data *)id->data; k5_cc_mutex_lock(context, &d->lock); krb5_mcc_free(context, id); d = (krb5_mcc_data *)id->data; ret = krb5_copy_principal(context, princ, &d->prin); update_mcc_change_time(d); if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) { /* Store client time offsets in the cache */ d->time_offset = os_ctx->time_offset; d->usec_offset = os_ctx->usec_offset; } k5_cc_mutex_unlock(context, &d->lock); if (ret == KRB5_OK) krb5_change_cache(); return ret; }
/* * Effects: * Destroys the contents of id. id is invalid after call. */ krb5_error_code KRB5_CALLCONV krb5_mcc_destroy(krb5_context context, krb5_ccache id) { krb5_mcc_data *d = id->data; krb5_boolean removed_from_table = FALSE; /* Remove this node from the table if it is still present. */ k5_cc_mutex_lock(context, &krb5int_mcc_mutex); if (k5_hashtab_remove(mcc_hashtab, d->name, strlen(d->name))) removed_from_table = TRUE; k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); /* Empty the cache and remove the reference for the table slot. There will * always be at least one reference left for the handle being destroyed. */ k5_cc_mutex_lock(context, &d->lock); empty_mcc_cache(context, d); if (removed_from_table) d->refcount--; k5_cc_mutex_unlock(context, &d->lock); /* Invalidate the handle, possibly removing the last reference to d and * freeing it. */ krb5_mcc_close(context, id); krb5_change_cache (); return KRB5_OK; }
krb5_error_code KRB5_CALLCONV krb5_mcc_generate_new (krb5_context context, krb5_ccache *id) { krb5_ccache lid; char uniquename[8]; krb5_error_code err; krb5_mcc_data *d; /* Allocate memory */ lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); if (lid == NULL) return KRB5_CC_NOMEM; lid->ops = &krb5_mcc_ops; err = k5_cc_mutex_lock(context, &krb5int_mcc_mutex); if (err) { free(lid); return err; } /* Check for uniqueness with mutex locked to avoid race conditions */ while (1) { krb5_mcc_list_node *ptr; err = krb5int_random_string (context, uniquename, sizeof (uniquename)); if (err) { k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); free(lid); return err; } for (ptr = mcc_head; ptr; ptr=ptr->next) { if (!strcmp(ptr->cache->name, uniquename)) { break; /* got a match, loop again */ } } if (!ptr) break; /* got to the end without finding a match */ } err = new_mcc_data(uniquename, &d); k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); if (err) { free(lid); return err; } lid->data = d; *id = lid; krb5_change_cache (); return KRB5_OK; }
krb5_error_code KRB5_CALLCONV krb5_mcc_generate_new (krb5_context context, krb5_ccache *id) { krb5_ccache lid; char uniquename[8]; krb5_error_code err; krb5_mcc_data *d; /* Allocate memory */ lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); if (lid == NULL) return KRB5_CC_NOMEM; lid->ops = &krb5_mcc_ops; k5_cc_mutex_lock(context, &krb5int_mcc_mutex); init_table(context); /* Check for uniqueness with mutex locked to avoid race conditions */ while (1) { err = krb5int_random_string (context, uniquename, sizeof (uniquename)); if (err) { k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); free(lid); return err; } if (k5_hashtab_get(mcc_hashtab, uniquename, strlen(uniquename)) == NULL) break; } err = new_mcc_data(uniquename, &d); k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); if (err) { free(lid); return err; } lid->data = d; *id = lid; krb5_change_cache (); return KRB5_OK; }
/* * Modifies: * id * * Effects: * Creates/refreshes the memory cred cache id. If the cache exists, its * contents are destroyed. * * Errors: * system errors */ krb5_error_code KRB5_CALLCONV krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) { krb5_error_code ret; krb5_mcc_data *d; d = (krb5_mcc_data *)id->data; ret = k5_cc_mutex_lock(context, &d->lock); if (ret) return ret; krb5_mcc_free(context, id); d = (krb5_mcc_data *)id->data; ret = krb5_copy_principal(context, princ, &d->prin); update_mcc_change_time(d); k5_cc_mutex_unlock(context, &d->lock); if (ret == KRB5_OK) krb5_change_cache(); return ret; }
/* Destroy the cache file and release the handle. */ static krb5_error_code KRB5_CALLCONV fcc_destroy(krb5_context context, krb5_ccache id) { krb5_error_code ret = 0; fcc_data *data = id->data; int st, fd; struct stat buf; unsigned long i, size; unsigned int wlen; char zeros[BUFSIZ]; k5_cc_mutex_lock(context, &data->lock); if (OPENCLOSE(id)) { invalidate_cache(data); fd = THREEPARAMOPEN(data->filename, O_RDWR | O_BINARY, 0); if (fd < 0) { ret = interpret_errno(context, errno); goto cleanup; } set_cloexec_fd(fd); data->fd = fd; } else { fcc_lseek(data, 0, SEEK_SET); } #ifdef MSDOS_FILESYSTEM /* * "Disgusting bit of UNIX trivia" - that's how the writers of NFS describe * the ability of UNIX to still write to a file which has been unlinked. * Naturally, the PC can't do this. As a result, we have to delete the * file after we wipe it clean, but that throws off all the error handling * code. So we have do the work ourselves. */ st = fstat(data->fd, &buf); if (st == -1) { ret = interpret_errno(context, errno); size = 0; /* Nothing to wipe clean */ } else { size = (unsigned long)buf.st_size; } memset(zeros, 0, BUFSIZ); while (size > 0) { wlen = (int)((size > BUFSIZ) ? BUFSIZ : size); /* How much to write */ i = write(data->fd, zeros, wlen); if (i < 0) { ret = interpret_errno(context, errno); /* Don't jump to cleanup--we still want to delete the file. */ break; } size -= i; } if (OPENCLOSE(id)) { (void)close(((fcc_data *)id->data)->fd); data->fd = -1; } st = unlink(data->filename); if (st < 0) { ret = interpret_errno(context, errno); goto cleanup; } #else /* MSDOS_FILESYSTEM */ st = unlink(data->filename); if (st < 0) { ret = interpret_errno(context, errno); if (OPENCLOSE(id)) { (void)close(data->fd); data->fd = -1; } goto cleanup; } st = fstat(data->fd, &buf); if (st < 0) { ret = interpret_errno(context, errno); if (OPENCLOSE(id)) { (void)close(data->fd); data->fd = -1; } goto cleanup; } /* XXX This may not be legal XXX */ size = (unsigned long)buf.st_size; memset(zeros, 0, BUFSIZ); for (i = 0; i < size / BUFSIZ; i++) { if (write(data->fd, zeros, BUFSIZ) < 0) { ret = interpret_errno(context, errno); if (OPENCLOSE(id)) { (void)close(data->fd); data->fd = -1; } goto cleanup; } } wlen = size % BUFSIZ; if (write(data->fd, zeros, wlen) < 0) { ret = interpret_errno(context, errno); if (OPENCLOSE(id)) { (void)close(data->fd); data->fd = -1; } goto cleanup; } st = close(data->fd); data->fd = -1; if (st) ret = interpret_errno(context, errno); #endif /* MSDOS_FILESYSTEM */ cleanup: k5_cc_mutex_unlock(context, &data->lock); dereference(context, data); free(id); krb5_change_cache(); return ret; }