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
krb5int_rc_finish_init(void)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 }
krb5int_rc_terminate(void)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*/
krb5_rc_register_type(krb5_context context,const krb5_rc_ops * ops)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*/
krb5_rc_resolve_type(krb5_context context,krb5_rcache * id,char * type)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*/
krb5_rc_get_type(krb5_context context,krb5_rcache id)131 char * krb5_rc_get_type(krb5_context context, krb5_rcache id)
132 {
133 return id->ops->type;
134 }
135
krb5_rc_default_type(krb5_context context)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*/
krb5_rc_default_name(krb5_context context)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
krb5_rc_default(krb5_context context,krb5_rcache * id)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
krb5_rc_resolve_full(krb5_context context,krb5_rcache * id,char * string_name)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