xref: /titanic_51/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.c (revision 159d09a20817016f09b3ea28d1bdada4a336bb91)
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 
29 struct krb5_rc_typelist {
30     const krb5_rc_ops *ops;
31     struct krb5_rc_typelist *next;
32 };
33 static struct krb5_rc_typelist none = { &krb5_rc_none_ops, 0 };
34 static struct krb5_rc_typelist rc_mem_type = { &krb5_rc_mem_ops, &none };
35 static struct krb5_rc_typelist krb5_rc_typelist_dfl = { &krb5_rc_file_ops, &rc_mem_type };
36 static struct krb5_rc_typelist *typehead = &krb5_rc_typelist_dfl;
37 static k5_mutex_t rc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
38 
39 int 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 }
50 void 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*/
83 krb5_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*/
110 krb5_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*/
131 char * krb5_rc_get_type(krb5_context context, krb5_rcache id)
132 {
133     return id->ops->type;
134 }
135 
136 char * 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*/
147 char * 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 
156 krb5_error_code
157 krb5_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 
180 krb5_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