17c478bd9Sstevel@tonic-gate /*
2159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * lib/krb5/rcache/rc_base.c
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * This file of the Kerberos V5 software is derived from public-domain code
117c478bd9Sstevel@tonic-gate  * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
12159d09a2SMark Phalan  *
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate 
167c478bd9Sstevel@tonic-gate /*
177c478bd9Sstevel@tonic-gate  * Base "glue" functions for the replay cache.
187c478bd9Sstevel@tonic-gate  */
197c478bd9Sstevel@tonic-gate 
207c478bd9Sstevel@tonic-gate #include "rc_base.h"
217c478bd9Sstevel@tonic-gate #include "rc_common.h"
227c478bd9Sstevel@tonic-gate #include "rc_mem.h"
237c478bd9Sstevel@tonic-gate #include "rc_file.h"
24159d09a2SMark Phalan #include "k5-thread.h"
257c478bd9Sstevel@tonic-gate 
26159d09a2SMark Phalan /* Solaris Kerberos */
277c478bd9Sstevel@tonic-gate #define FREE_RC(x) ((void) free((char *) (x)))
287c478bd9Sstevel@tonic-gate 
29159d09a2SMark Phalan struct krb5_rc_typelist {
30159d09a2SMark Phalan     const krb5_rc_ops *ops;
31159d09a2SMark Phalan     struct krb5_rc_typelist *next;
32159d09a2SMark Phalan };
33159d09a2SMark Phalan static struct krb5_rc_typelist none = { &krb5_rc_none_ops, 0 };
34159d09a2SMark Phalan static struct krb5_rc_typelist rc_mem_type = { &krb5_rc_mem_ops, &none };
35159d09a2SMark Phalan static struct krb5_rc_typelist krb5_rc_typelist_dfl = { &krb5_rc_file_ops, &rc_mem_type };
367c478bd9Sstevel@tonic-gate static struct krb5_rc_typelist *typehead = &krb5_rc_typelist_dfl;
37505d05c7Sgtb static k5_mutex_t rc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
387c478bd9Sstevel@tonic-gate 
krb5int_rc_finish_init(void)39505d05c7Sgtb int krb5int_rc_finish_init(void)
40505d05c7Sgtb {
41159d09a2SMark Phalan     /* Solaris Kerberos */
4265d0d3dcSsemery     int retval;
4365d0d3dcSsemery 
4465d0d3dcSsemery     retval = k5_mutex_finish_init(&grcache.lock);
4565d0d3dcSsemery     if (retval)
4665d0d3dcSsemery 	return (retval);
4765d0d3dcSsemery 
48505d05c7Sgtb     return k5_mutex_finish_init(&rc_typelist_lock);
49505d05c7Sgtb }
krb5int_rc_terminate(void)50505d05c7Sgtb void krb5int_rc_terminate(void)
51505d05c7Sgtb {
52505d05c7Sgtb     struct krb5_rc_typelist *t, *t_next;
53159d09a2SMark Phalan     /* Solaris Kerberos */
5465d0d3dcSsemery     struct mem_data *tgr = (struct mem_data *)grcache.data;
5565d0d3dcSsemery     struct authlist *q, *qt;
5665d0d3dcSsemery     int i;
5765d0d3dcSsemery 
5865d0d3dcSsemery     k5_mutex_destroy(&grcache.lock);
5965d0d3dcSsemery 
6065d0d3dcSsemery     if (tgr != NULL) {
6165d0d3dcSsemery     	if (tgr->name)
6265d0d3dcSsemery 		free(tgr->name);
6365d0d3dcSsemery     	for (i = 0; i < tgr->hsize; i++)
6465d0d3dcSsemery 		for (q = tgr->h[i]; q; q = qt) {
6565d0d3dcSsemery 			qt = q->nh;
6665d0d3dcSsemery 			free(q->rep.server);
6765d0d3dcSsemery 			free(q->rep.client);
6865d0d3dcSsemery 			free(q);
6965d0d3dcSsemery 		}
7065d0d3dcSsemery     	if (tgr->h)
7165d0d3dcSsemery 		free(tgr->h);
7265d0d3dcSsemery     	free(tgr);
7365d0d3dcSsemery     }
7465d0d3dcSsemery 
75505d05c7Sgtb     k5_mutex_destroy(&rc_typelist_lock);
76505d05c7Sgtb     for (t = typehead; t != &krb5_rc_typelist_dfl; t = t_next) {
77505d05c7Sgtb 	t_next = t->next;
78505d05c7Sgtb 	free(t);
79505d05c7Sgtb     }
80505d05c7Sgtb }
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
krb5_rc_register_type(krb5_context context,const krb5_rc_ops * ops)83505d05c7Sgtb krb5_error_code krb5_rc_register_type(krb5_context context,
84505d05c7Sgtb 				      const krb5_rc_ops *ops)
857c478bd9Sstevel@tonic-gate {
86159d09a2SMark Phalan     struct krb5_rc_typelist *t;
87159d09a2SMark Phalan     krb5_error_code err;
88159d09a2SMark Phalan     err = k5_mutex_lock(&rc_typelist_lock);
89159d09a2SMark Phalan     if (err)
90505d05c7Sgtb 	return err;
91159d09a2SMark Phalan     for (t = typehead;t && strcmp(t->ops->type,ops->type);t = t->next)
92159d09a2SMark Phalan 	;
93159d09a2SMark Phalan     if (t) {
94159d09a2SMark Phalan 	k5_mutex_unlock(&rc_typelist_lock);
95159d09a2SMark Phalan 	return KRB5_RC_TYPE_EXISTS;
96159d09a2SMark Phalan     }
97159d09a2SMark Phalan     t = (struct krb5_rc_typelist *) malloc(sizeof(struct krb5_rc_typelist));
98159d09a2SMark Phalan     if (t == NULL) {
99505d05c7Sgtb 	k5_mutex_unlock(&rc_typelist_lock);
100505d05c7Sgtb 	return KRB5_RC_MALLOC;
101159d09a2SMark Phalan     }
102159d09a2SMark Phalan     t->next = typehead;
103159d09a2SMark Phalan     t->ops = ops;
104159d09a2SMark Phalan     typehead = t;
105159d09a2SMark Phalan     k5_mutex_unlock(&rc_typelist_lock);
106159d09a2SMark Phalan     return 0;
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /*ARGSUSED*/
krb5_rc_resolve_type(krb5_context context,krb5_rcache * id,char * type)110505d05c7Sgtb krb5_error_code krb5_rc_resolve_type(krb5_context context, krb5_rcache *id,
111505d05c7Sgtb 				     char *type)
112505d05c7Sgtb {
113505d05c7Sgtb     struct krb5_rc_typelist *t;
114505d05c7Sgtb     krb5_error_code err;
115505d05c7Sgtb     err = k5_mutex_lock(&rc_typelist_lock);
116505d05c7Sgtb     if (err)
117505d05c7Sgtb 	return err;
118505d05c7Sgtb     for (t = typehead;t && strcmp(t->ops->type,type);t = t->next)
119505d05c7Sgtb 	;
120505d05c7Sgtb     if (!t) {
121505d05c7Sgtb 	k5_mutex_unlock(&rc_typelist_lock);
122505d05c7Sgtb 	return KRB5_RC_TYPE_NOTFOUND;
123505d05c7Sgtb     }
124505d05c7Sgtb     /* allocate *id? nah */
125505d05c7Sgtb     (*id)->ops = t->ops;
126505d05c7Sgtb     k5_mutex_unlock(&rc_typelist_lock);
127505d05c7Sgtb     return k5_mutex_init(&(*id)->lock);
128505d05c7Sgtb }
129505d05c7Sgtb 
130505d05c7Sgtb /*ARGSUSED*/
krb5_rc_get_type(krb5_context context,krb5_rcache id)131505d05c7Sgtb char * krb5_rc_get_type(krb5_context context, krb5_rcache id)
1327c478bd9Sstevel@tonic-gate {
133159d09a2SMark Phalan     return id->ops->type;
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
krb5_rc_default_type(krb5_context context)136159d09a2SMark Phalan char * krb5_rc_default_type(krb5_context context)
137505d05c7Sgtb {
1384ef135ebSsemery 	/*
1394ef135ebSsemery 	 * Solaris Kerberos/SUNW14resync
1404ef135ebSsemery 	 * MIT's is "dfl" but we now have FILE and MEMORY instead.
1414ef135ebSsemery 	 * And we only support the KRB5RCNAME env var.
1424ef135ebSsemery 	 */
1434ef135ebSsemery 	return ("FILE");
144505d05c7Sgtb }
145505d05c7Sgtb 
1467c478bd9Sstevel@tonic-gate /*ARGSUSED*/
krb5_rc_default_name(krb5_context context)147505d05c7Sgtb char * krb5_rc_default_name(krb5_context context)
1487c478bd9Sstevel@tonic-gate {
149159d09a2SMark Phalan     char *s;
150159d09a2SMark Phalan     if ((s = getenv("KRB5RCNAME")))
151159d09a2SMark Phalan 	return s;
152159d09a2SMark Phalan     else
153159d09a2SMark Phalan 	return (char *) 0;
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate krb5_error_code
krb5_rc_default(krb5_context context,krb5_rcache * id)157505d05c7Sgtb krb5_rc_default(krb5_context context, krb5_rcache *id)
1587c478bd9Sstevel@tonic-gate {
1597c478bd9Sstevel@tonic-gate     krb5_error_code retval;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate     if (!(*id = (krb5_rcache )malloc(sizeof(**id))))
1627c478bd9Sstevel@tonic-gate 	return KRB5_RC_MALLOC;
1637c478bd9Sstevel@tonic-gate 
164*55fea89dSDan Cross     if ((retval = krb5_rc_resolve_type(context, id,
165159d09a2SMark Phalan 				       krb5_rc_default_type(context)))) {
1664ef135ebSsemery 	FREE_RC(*id);
167159d09a2SMark Phalan 	return retval;
1684ef135ebSsemery     }
169*55fea89dSDan Cross     if ((retval = krb5_rc_resolve(context, *id,
170159d09a2SMark Phalan 				  krb5_rc_default_name(context)))) {
171159d09a2SMark Phalan 	k5_mutex_destroy(&(*id)->lock);
1727c478bd9Sstevel@tonic-gate 	FREE_RC(*id);
173505d05c7Sgtb 	return retval;
174505d05c7Sgtb     }
1757c478bd9Sstevel@tonic-gate     (*id)->magic = KV5M_RCACHE;
1767c478bd9Sstevel@tonic-gate     return retval;
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate 
179159d09a2SMark Phalan 
krb5_rc_resolve_full(krb5_context context,krb5_rcache * id,char * string_name)180505d05c7Sgtb krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char *string_name)
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate     char *type;
1837c478bd9Sstevel@tonic-gate     char *residual;
1847c478bd9Sstevel@tonic-gate     krb5_error_code retval;
185505d05c7Sgtb     unsigned int diff;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate     if (!(residual = strchr(string_name,':')))
1887c478bd9Sstevel@tonic-gate 	return KRB5_RC_PARSE;
189*55fea89dSDan Cross 
190505d05c7Sgtb     diff = residual - string_name;
191505d05c7Sgtb     if (!(type = malloc(diff + 1)))
1927c478bd9Sstevel@tonic-gate 	return KRB5_RC_MALLOC;
193505d05c7Sgtb     (void) strncpy(type, string_name, diff);
1947c478bd9Sstevel@tonic-gate     type[residual - string_name] = '\0';
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate     if (!(*id = (krb5_rcache) malloc(sizeof(**id)))) {
1977c478bd9Sstevel@tonic-gate 	FREE_RC(type);
1987c478bd9Sstevel@tonic-gate 	return KRB5_RC_MALLOC;
1997c478bd9Sstevel@tonic-gate     }
2007c478bd9Sstevel@tonic-gate 
201159d09a2SMark Phalan     if ((retval = krb5_rc_resolve_type(context, id,type))) {
202505d05c7Sgtb 	FREE_RC(type);
203505d05c7Sgtb 	FREE_RC(*id);
204505d05c7Sgtb 	return retval;
205505d05c7Sgtb     }
2067c478bd9Sstevel@tonic-gate     FREE_RC(type);
207159d09a2SMark Phalan     if ((retval = krb5_rc_resolve(context, *id,residual + 1))) {
208159d09a2SMark Phalan 	k5_mutex_destroy(&(*id)->lock);
2097c478bd9Sstevel@tonic-gate 	FREE_RC(*id);
210505d05c7Sgtb 	return retval;
211505d05c7Sgtb     }
2127c478bd9Sstevel@tonic-gate     (*id)->magic = KV5M_RCACHE;
2137c478bd9Sstevel@tonic-gate     return retval;
2147c478bd9Sstevel@tonic-gate }
215159d09a2SMark Phalan 
216