rc_base.c revision 7934:6aeeafc994de
1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6
7/*
8 * lib/krb5/rcache/rc_base.c
9 *
10 * This file of the Kerberos V5 software is derived from public-domain code
11 * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
12 *
13 */
14
15
16/*
17 * Base "glue" functions for the replay cache.
18 */
19
20#include "rc_base.h"
21#include "rc_common.h"
22#include "rc_mem.h"
23#include "rc_file.h"
24#include "k5-thread.h"
25
26/* Solaris Kerberos */
27#define FREE_RC(x) ((void) free((char *) (x)))
28
29struct krb5_rc_typelist {
30    const krb5_rc_ops *ops;
31    struct krb5_rc_typelist *next;
32};
33static struct krb5_rc_typelist none = { &krb5_rc_none_ops, 0 };
34static struct krb5_rc_typelist rc_mem_type = { &krb5_rc_mem_ops, &none };
35static struct krb5_rc_typelist krb5_rc_typelist_dfl = { &krb5_rc_file_ops, &rc_mem_type };
36static struct krb5_rc_typelist *typehead = &krb5_rc_typelist_dfl;
37static k5_mutex_t rc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
38
39int krb5int_rc_finish_init(void)
40{
41    /* Solaris Kerberos */
42    int retval;
43
44    retval = k5_mutex_finish_init(&grcache.lock);
45    if (retval)
46	return (retval);
47
48    return k5_mutex_finish_init(&rc_typelist_lock);
49}
50void krb5int_rc_terminate(void)
51{
52    struct krb5_rc_typelist *t, *t_next;
53    /* Solaris Kerberos */
54    struct mem_data *tgr = (struct mem_data *)grcache.data;
55    struct authlist *q, *qt;
56    int i;
57
58    k5_mutex_destroy(&grcache.lock);
59
60    if (tgr != NULL) {
61    	if (tgr->name)
62		free(tgr->name);
63    	for (i = 0; i < tgr->hsize; i++)
64		for (q = tgr->h[i]; q; q = qt) {
65			qt = q->nh;
66			free(q->rep.server);
67			free(q->rep.client);
68			free(q);
69		}
70    	if (tgr->h)
71		free(tgr->h);
72    	free(tgr);
73    }
74
75    k5_mutex_destroy(&rc_typelist_lock);
76    for (t = typehead; t != &krb5_rc_typelist_dfl; t = t_next) {
77	t_next = t->next;
78	free(t);
79    }
80}
81
82/*ARGSUSED*/
83krb5_error_code krb5_rc_register_type(krb5_context context,
84				      const krb5_rc_ops *ops)
85{
86    struct krb5_rc_typelist *t;
87    krb5_error_code err;
88    err = k5_mutex_lock(&rc_typelist_lock);
89    if (err)
90	return err;
91    for (t = typehead;t && strcmp(t->ops->type,ops->type);t = t->next)
92	;
93    if (t) {
94	k5_mutex_unlock(&rc_typelist_lock);
95	return KRB5_RC_TYPE_EXISTS;
96    }
97    t = (struct krb5_rc_typelist *) malloc(sizeof(struct krb5_rc_typelist));
98    if (t == NULL) {
99	k5_mutex_unlock(&rc_typelist_lock);
100	return KRB5_RC_MALLOC;
101    }
102    t->next = typehead;
103    t->ops = ops;
104    typehead = t;
105    k5_mutex_unlock(&rc_typelist_lock);
106    return 0;
107}
108
109/*ARGSUSED*/
110krb5_error_code krb5_rc_resolve_type(krb5_context context, krb5_rcache *id,
111				     char *type)
112{
113    struct krb5_rc_typelist *t;
114    krb5_error_code err;
115    err = k5_mutex_lock(&rc_typelist_lock);
116    if (err)
117	return err;
118    for (t = typehead;t && strcmp(t->ops->type,type);t = t->next)
119	;
120    if (!t) {
121	k5_mutex_unlock(&rc_typelist_lock);
122	return KRB5_RC_TYPE_NOTFOUND;
123    }
124    /* allocate *id? nah */
125    (*id)->ops = t->ops;
126    k5_mutex_unlock(&rc_typelist_lock);
127    return k5_mutex_init(&(*id)->lock);
128}
129
130/*ARGSUSED*/
131char * krb5_rc_get_type(krb5_context context, krb5_rcache id)
132{
133    return id->ops->type;
134}
135
136char * krb5_rc_default_type(krb5_context context)
137{
138	/*
139	 * Solaris Kerberos/SUNW14resync
140	 * MIT's is "dfl" but we now have FILE and MEMORY instead.
141	 * And we only support the KRB5RCNAME env var.
142	 */
143	return ("FILE");
144}
145
146/*ARGSUSED*/
147char * krb5_rc_default_name(krb5_context context)
148{
149    char *s;
150    if ((s = getenv("KRB5RCNAME")))
151	return s;
152    else
153	return (char *) 0;
154}
155
156krb5_error_code
157krb5_rc_default(krb5_context context, krb5_rcache *id)
158{
159    krb5_error_code retval;
160
161    if (!(*id = (krb5_rcache )malloc(sizeof(**id))))
162	return KRB5_RC_MALLOC;
163
164    if ((retval = krb5_rc_resolve_type(context, id,
165				       krb5_rc_default_type(context)))) {
166	FREE_RC(*id);
167	return retval;
168    }
169    if ((retval = krb5_rc_resolve(context, *id,
170				  krb5_rc_default_name(context)))) {
171	k5_mutex_destroy(&(*id)->lock);
172	FREE_RC(*id);
173	return retval;
174    }
175    (*id)->magic = KV5M_RCACHE;
176    return retval;
177}
178
179
180krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char *string_name)
181{
182    char *type;
183    char *residual;
184    krb5_error_code retval;
185    unsigned int diff;
186
187    if (!(residual = strchr(string_name,':')))
188	return KRB5_RC_PARSE;
189
190    diff = residual - string_name;
191    if (!(type = malloc(diff + 1)))
192	return KRB5_RC_MALLOC;
193    (void) strncpy(type, string_name, diff);
194    type[residual - string_name] = '\0';
195
196    if (!(*id = (krb5_rcache) malloc(sizeof(**id)))) {
197	FREE_RC(type);
198	return KRB5_RC_MALLOC;
199    }
200
201    if ((retval = krb5_rc_resolve_type(context, id,type))) {
202	FREE_RC(type);
203	FREE_RC(*id);
204	return retval;
205    }
206    FREE_RC(type);
207    if ((retval = krb5_rc_resolve(context, *id,residual + 1))) {
208	k5_mutex_destroy(&(*id)->lock);
209	FREE_RC(*id);
210	return retval;
211    }
212    (*id)->magic = KV5M_RCACHE;
213    return retval;
214}
215
216