rc_base.c revision 69dc090717e863b0d20b53b7b1e576d25aa0b28d
505d05c73a6e56769f263d4803b22eddd168ee24gtb/*
004388ebfdfe2ed7dfd2d153a876dfcc22d2c006casper * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
505d05c73a6e56769f263d4803b22eddd168ee24gtb * Use is subject to license terms.
505d05c73a6e56769f263d4803b22eddd168ee24gtb */
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb#pragma ident "%Z%%M% %I% %E% SMI"
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb/*
505d05c73a6e56769f263d4803b22eddd168ee24gtb * lib/krb5/rcache/rc_base.c
505d05c73a6e56769f263d4803b22eddd168ee24gtb *
505d05c73a6e56769f263d4803b22eddd168ee24gtb * This file of the Kerberos V5 software is derived from public-domain code
505d05c73a6e56769f263d4803b22eddd168ee24gtb * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
505d05c73a6e56769f263d4803b22eddd168ee24gtb */
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb/*
505d05c73a6e56769f263d4803b22eddd168ee24gtb * Base "glue" functions for the replay cache.
505d05c73a6e56769f263d4803b22eddd168ee24gtb */
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb#include "rc_base.h"
505d05c73a6e56769f263d4803b22eddd168ee24gtb#include "rc_common.h"
505d05c73a6e56769f263d4803b22eddd168ee24gtb#include "rc_mem.h"
505d05c73a6e56769f263d4803b22eddd168ee24gtb#include "rc_file.h"
505d05c73a6e56769f263d4803b22eddd168ee24gtb#include <k5-thread.h>
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb#define FREE_RC(x) ((void) free((char *) (x)))
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtbstruct krb5_rc_typelist
505d05c73a6e56769f263d4803b22eddd168ee24gtb {
505d05c73a6e56769f263d4803b22eddd168ee24gtb const krb5_rc_ops *ops;
505d05c73a6e56769f263d4803b22eddd168ee24gtb struct krb5_rc_typelist *next;
505d05c73a6e56769f263d4803b22eddd168ee24gtb };
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtbstatic struct krb5_rc_typelist rc_none_type = { &krb5_rc_none_ops, 0 };
505d05c73a6e56769f263d4803b22eddd168ee24gtbstatic struct krb5_rc_typelist rc_mem_type =
505d05c73a6e56769f263d4803b22eddd168ee24gtb { &krb5_rc_mem_ops, &rc_none_type };
505d05c73a6e56769f263d4803b22eddd168ee24gtbstatic struct krb5_rc_typelist krb5_rc_typelist_dfl =
505d05c73a6e56769f263d4803b22eddd168ee24gtb { &krb5_rc_file_ops, &rc_mem_type };
505d05c73a6e56769f263d4803b22eddd168ee24gtbstatic struct krb5_rc_typelist *typehead = &krb5_rc_typelist_dfl;
505d05c73a6e56769f263d4803b22eddd168ee24gtbstatic k5_mutex_t rc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtbint krb5int_rc_finish_init(void)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb int retval;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb retval = k5_mutex_finish_init(&grcache.lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (retval)
505d05c73a6e56769f263d4803b22eddd168ee24gtb return (retval);
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb return k5_mutex_finish_init(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtbvoid krb5int_rc_terminate(void)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb struct krb5_rc_typelist *t, *t_next;
505d05c73a6e56769f263d4803b22eddd168ee24gtb struct mem_data *tgr = (struct mem_data *)grcache.data;
505d05c73a6e56769f263d4803b22eddd168ee24gtb struct authlist *q, *qt;
505d05c73a6e56769f263d4803b22eddd168ee24gtb int i;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_destroy(&grcache.lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (tgr != NULL) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (tgr->name)
505d05c73a6e56769f263d4803b22eddd168ee24gtb free(tgr->name);
505d05c73a6e56769f263d4803b22eddd168ee24gtb for (i = 0; i < tgr->hsize; i++)
505d05c73a6e56769f263d4803b22eddd168ee24gtb for (q = tgr->h[i]; q; q = qt) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb qt = q->nh;
505d05c73a6e56769f263d4803b22eddd168ee24gtb free(q->rep.server);
505d05c73a6e56769f263d4803b22eddd168ee24gtb free(q->rep.client);
505d05c73a6e56769f263d4803b22eddd168ee24gtb free(q);
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (tgr->h)
505d05c73a6e56769f263d4803b22eddd168ee24gtb free(tgr->h);
505d05c73a6e56769f263d4803b22eddd168ee24gtb free(tgr);
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_destroy(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb for (t = typehead; t != &krb5_rc_typelist_dfl; t = t_next) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb t_next = t->next;
505d05c73a6e56769f263d4803b22eddd168ee24gtb free(t);
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb/*ARGSUSED*/
505d05c73a6e56769f263d4803b22eddd168ee24gtbkrb5_error_code krb5_rc_register_type(krb5_context context,
505d05c73a6e56769f263d4803b22eddd168ee24gtb const krb5_rc_ops *ops)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb struct krb5_rc_typelist *t;
505d05c73a6e56769f263d4803b22eddd168ee24gtb krb5_error_code err;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb err = k5_mutex_lock(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (err)
505d05c73a6e56769f263d4803b22eddd168ee24gtb return err;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb for (t = typehead;t && strcmp(t->ops->type,ops->type);t = t->next)
505d05c73a6e56769f263d4803b22eddd168ee24gtb ;
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (t) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_unlock(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return KRB5_RC_TYPE_EXISTS;
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb t = (struct krb5_rc_typelist *) malloc(sizeof(struct krb5_rc_typelist));
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (t == NULL) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_unlock(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return KRB5_RC_MALLOC;
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb t->next = typehead;
505d05c73a6e56769f263d4803b22eddd168ee24gtb t->ops = ops;
505d05c73a6e56769f263d4803b22eddd168ee24gtb typehead = t;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_unlock(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return 0;
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb/*ARGSUSED*/
505d05c73a6e56769f263d4803b22eddd168ee24gtbkrb5_error_code krb5_rc_resolve_type(krb5_context context, krb5_rcache *id,
505d05c73a6e56769f263d4803b22eddd168ee24gtb char *type)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb struct krb5_rc_typelist *t;
505d05c73a6e56769f263d4803b22eddd168ee24gtb krb5_error_code err;
505d05c73a6e56769f263d4803b22eddd168ee24gtb err = k5_mutex_lock(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (err)
505d05c73a6e56769f263d4803b22eddd168ee24gtb return err;
505d05c73a6e56769f263d4803b22eddd168ee24gtb for (t = typehead;t && strcmp(t->ops->type,type);t = t->next)
505d05c73a6e56769f263d4803b22eddd168ee24gtb ;
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (!t) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_unlock(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return KRB5_RC_TYPE_NOTFOUND;
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb /* allocate *id? nah */
505d05c73a6e56769f263d4803b22eddd168ee24gtb (*id)->ops = t->ops;
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_unlock(&rc_typelist_lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return k5_mutex_init(&(*id)->lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb/*ARGSUSED*/
505d05c73a6e56769f263d4803b22eddd168ee24gtbchar * krb5_rc_get_type(krb5_context context, krb5_rcache id)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb return id->ops->type;
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtbchar * krb5_rc_default_type(krb5_context context)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb /*
505d05c73a6e56769f263d4803b22eddd168ee24gtb * Solaris Kerberos/SUNW14resync
505d05c73a6e56769f263d4803b22eddd168ee24gtb * MIT's is "dfl" but we now have FILE and MEMORY instead.
505d05c73a6e56769f263d4803b22eddd168ee24gtb * And we only support the KRB5RCNAME env var.
505d05c73a6e56769f263d4803b22eddd168ee24gtb */
505d05c73a6e56769f263d4803b22eddd168ee24gtb return ("FILE");
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb/*ARGSUSED*/
505d05c73a6e56769f263d4803b22eddd168ee24gtbchar * krb5_rc_default_name(krb5_context context)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb char *s;
505d05c73a6e56769f263d4803b22eddd168ee24gtb if ((s = getenv("KRB5RCNAME")))
505d05c73a6e56769f263d4803b22eddd168ee24gtb return s;
505d05c73a6e56769f263d4803b22eddd168ee24gtb else
505d05c73a6e56769f263d4803b22eddd168ee24gtb return (char *) 0;
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtbkrb5_error_code
505d05c73a6e56769f263d4803b22eddd168ee24gtbkrb5_rc_default(krb5_context context, krb5_rcache *id)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb krb5_error_code retval;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (!(*id = (krb5_rcache )malloc(sizeof(**id))))
505d05c73a6e56769f263d4803b22eddd168ee24gtb return KRB5_RC_MALLOC;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb retval = krb5_rc_resolve_type(context, id, krb5_rc_default_type(context));
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (retval != 0) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb /*
505d05c73a6e56769f263d4803b22eddd168ee24gtb * k5_mutex_destroy() is not called here, because the mutex had
505d05c73a6e56769f263d4803b22eddd168ee24gtb * not been successfully initialized by krb5_rc_resolve_type().
505d05c73a6e56769f263d4803b22eddd168ee24gtb */
505d05c73a6e56769f263d4803b22eddd168ee24gtb FREE_RC(*id);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return (retval);
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb retval = krb5_rc_resolve(context, *id, krb5_rc_default_name(context));
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (retval) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_destroy(&(*id)->lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb FREE_RC(*id);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return retval;
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb (*id)->magic = KV5M_RCACHE;
505d05c73a6e56769f263d4803b22eddd168ee24gtb return retval;
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtbkrb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char *string_name)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb char *type;
505d05c73a6e56769f263d4803b22eddd168ee24gtb char *residual;
505d05c73a6e56769f263d4803b22eddd168ee24gtb krb5_error_code retval;
505d05c73a6e56769f263d4803b22eddd168ee24gtb unsigned int diff;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (!(residual = strchr(string_name,':')))
505d05c73a6e56769f263d4803b22eddd168ee24gtb return KRB5_RC_PARSE;
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb diff = residual - string_name;
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (!(type = malloc(diff + 1)))
505d05c73a6e56769f263d4803b22eddd168ee24gtb return KRB5_RC_MALLOC;
505d05c73a6e56769f263d4803b22eddd168ee24gtb (void) strncpy(type, string_name, diff);
505d05c73a6e56769f263d4803b22eddd168ee24gtb type[residual - string_name] = '\0';
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (!(*id = (krb5_rcache) malloc(sizeof(**id)))) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb FREE_RC(type);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return KRB5_RC_MALLOC;
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb
505d05c73a6e56769f263d4803b22eddd168ee24gtb retval = krb5_rc_resolve_type(context, id, type);
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (retval != 0) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb /*
505d05c73a6e56769f263d4803b22eddd168ee24gtb * k5_mutex_destroy() is not called here, because the mutex had
505d05c73a6e56769f263d4803b22eddd168ee24gtb * not been successfully initialized by krb5_rc_resolve_type().
505d05c73a6e56769f263d4803b22eddd168ee24gtb */
505d05c73a6e56769f263d4803b22eddd168ee24gtb FREE_RC(type);
505d05c73a6e56769f263d4803b22eddd168ee24gtb FREE_RC(*id);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return retval;
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb FREE_RC(type);
505d05c73a6e56769f263d4803b22eddd168ee24gtb retval = krb5_rc_resolve(context, *id, residual + 1);
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (retval) {
505d05c73a6e56769f263d4803b22eddd168ee24gtb k5_mutex_destroy(&(*id)->lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb FREE_RC(*id);
505d05c73a6e56769f263d4803b22eddd168ee24gtb return retval;
505d05c73a6e56769f263d4803b22eddd168ee24gtb }
505d05c73a6e56769f263d4803b22eddd168ee24gtb (*id)->magic = KV5M_RCACHE;
505d05c73a6e56769f263d4803b22eddd168ee24gtb return retval;
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb