8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / gss_mechs / mech_krb5 / krb5 / ccache / ccbase.c
blob89ec1ad9ca4dbd1d8f857d650a31a2420724bcd3
1 /*
2 * lib/krb5/ccache/ccbase.c
4 * Copyright 1990,2004 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
27 * Registration functions for ccache.
31 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
32 * Use is subject to license terms.
36 #include "k5-int.h"
37 #include "k5-thread.h"
39 #include "fcc.h"
40 #include "cc-int.h"
42 struct krb5_cc_typelist {
43 const krb5_cc_ops *ops;
44 struct krb5_cc_typelist *next;
47 struct krb5_cc_typecursor {
48 struct krb5_cc_typelist *tptr;
50 /* typedef krb5_cc_typecursor in k5-int.h */
52 extern const krb5_cc_ops krb5_mcc_ops;
53 #ifdef USE_KEYRING_CCACHE
54 extern const krb5_cc_ops krb5_krcc_ops;
55 #endif
57 #ifdef _WIN32
58 extern const krb5_cc_ops krb5_lcc_ops;
59 static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL };
60 static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry };
61 #else
63 #ifdef USE_CCAPI_V3
64 extern const krb5_cc_ops krb5_cc_stdcc_ops;
65 static struct krb5_cc_typelist cc_stdcc_entry = { &krb5_cc_stdcc_ops, NULL };
66 static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_stdcc_entry };
67 #else
69 static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL };
70 #endif /* USE_CCAPI_V3 */
72 #ifdef USE_KEYRING_CCACHE
73 static struct krb5_cc_typelist cc_file_entry = { &krb5_cc_file_ops,
74 &cc_mcc_entry };
75 static struct krb5_cc_typelist cc_krcc_entry = { &krb5_krcc_ops,
76 &cc_file_entry };
77 #endif /* USE_KEYRING_CCACHE */
78 #endif
80 static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops,
81 &cc_mcc_entry };
82 #ifdef USE_KEYRING_CCACHE
83 #define INITIAL_TYPEHEAD (&cc_krcc_entry)
84 #else
85 #define INITIAL_TYPEHEAD (&cc_fcc_entry)
86 #endif
87 static struct krb5_cc_typelist *cc_typehead = INITIAL_TYPEHEAD;
88 static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
90 static krb5_error_code
91 krb5int_cc_getops(krb5_context, const char *, const krb5_cc_ops **);
93 int
94 krb5int_cc_initialize(void)
96 int err;
98 err = k5_mutex_finish_init(&krb5int_mcc_mutex);
99 if (err)
100 return err;
101 err = k5_mutex_finish_init(&cc_typelist_lock);
102 if (err)
103 return err;
104 err = k5_mutex_finish_init(&krb5int_cc_file_mutex);
105 if (err)
106 return err;
107 #ifdef USE_KEYRING_CCACHE
108 err = k5_mutex_finish_init(&krb5int_krcc_mutex);
109 if (err)
110 return err;
111 #endif
112 return 0;
115 void
116 krb5int_cc_finalize(void)
118 struct krb5_cc_typelist *t, *t_next;
119 k5_mutex_destroy(&cc_typelist_lock);
120 k5_mutex_destroy(&krb5int_cc_file_mutex);
121 k5_mutex_destroy(&krb5int_mcc_mutex);
122 #ifdef USE_KEYRING_CCACHE
123 k5_mutex_destroy(&krb5int_krcc_mutex);
124 #endif
125 for (t = cc_typehead; t != INITIAL_TYPEHEAD; t = t_next) {
126 t_next = t->next;
127 free(t);
133 * Register a new credentials cache type
134 * If override is set, replace any existing ccache with that type tag
137 krb5_error_code KRB5_CALLCONV
138 krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override)
140 struct krb5_cc_typelist *t;
141 krb5_error_code err;
143 err = k5_mutex_lock(&cc_typelist_lock);
144 if (err)
145 return err;
146 for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next)
148 if (t) {
149 if (override) {
150 t->ops = ops;
151 k5_mutex_unlock(&cc_typelist_lock);
152 return 0;
153 } else {
154 k5_mutex_unlock(&cc_typelist_lock);
155 return KRB5_CC_TYPE_EXISTS;
158 if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) {
159 k5_mutex_unlock(&cc_typelist_lock);
160 return ENOMEM;
162 t->next = cc_typehead;
163 t->ops = ops;
164 cc_typehead = t;
165 k5_mutex_unlock(&cc_typelist_lock);
166 return 0;
170 * Resolve a credential cache name into a cred. cache object.
172 * The name is currently constrained to be of the form "type:residual";
174 * The "type" portion corresponds to one of the predefined credential
175 * cache types, while the "residual" portion is specific to the
176 * particular cache type.
179 #include <ctype.h>
180 krb5_error_code KRB5_CALLCONV
181 krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache)
183 char *pfx, *cp;
184 const char *resid;
185 unsigned int pfxlen;
186 krb5_error_code err;
187 const krb5_cc_ops *ops;
189 /* Solaris Kerberos */
190 if (!name)
191 return KRB5_CC_BADNAME;
193 pfx = NULL;
194 cp = strchr (name, ':');
195 if (!cp) {
196 if (krb5_cc_dfl_ops)
197 return (*krb5_cc_dfl_ops->resolve)(context, cache, name);
198 else
199 return KRB5_CC_BADNAME;
202 pfxlen = cp - name;
204 if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) {
205 /* We found a drive letter not a prefix - use FILE */
206 pfx = strdup("FILE");
207 if (!pfx)
208 return ENOMEM;
210 resid = name;
211 } else {
212 resid = name + pfxlen + 1;
214 pfx = malloc (pfxlen+1);
215 if (!pfx)
216 return ENOMEM;
218 memcpy (pfx, name, pfxlen);
219 pfx[pfxlen] = '\0';
222 *cache = (krb5_ccache) 0;
224 err = krb5int_cc_getops(context, pfx, &ops);
225 if (pfx != NULL)
226 free(pfx);
227 if (err)
228 return err;
230 return ops->resolve(context, cache, resid);
234 * cc_getops
236 * Internal function to return the ops vector for a given ccache
237 * prefix string.
239 static krb5_error_code
240 krb5int_cc_getops(
241 krb5_context context,
242 const char *pfx,
243 const krb5_cc_ops **ops)
245 krb5_error_code err;
246 struct krb5_cc_typelist *tlist;
248 err = k5_mutex_lock(&cc_typelist_lock);
249 if (err)
250 return err;
252 for (tlist = cc_typehead; tlist; tlist = tlist->next) {
253 if (strcmp (tlist->ops->prefix, pfx) == 0) {
254 *ops = tlist->ops;
255 k5_mutex_unlock(&cc_typelist_lock);
256 return 0;
259 k5_mutex_unlock(&cc_typelist_lock);
260 if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) {
261 *ops = krb5_cc_dfl_ops;
262 return 0;
264 return KRB5_CC_UNKNOWN_TYPE;
268 * cc_new_unique
270 * Generate a new unique ccache, given a ccache type and a hint
271 * string. Ignores the hint string for now.
273 krb5_error_code KRB5_CALLCONV
274 krb5_cc_new_unique(
275 krb5_context context,
276 const char *type,
277 const char *hint,
278 krb5_ccache *id)
280 const krb5_cc_ops *ops;
281 krb5_error_code err;
283 *id = NULL;
285 err = krb5int_cc_getops(context, type, &ops);
286 if (err)
287 return err;
289 return ops->gen_new(context, id);
293 * cc_typecursor
295 * Note: to avoid copying the typelist at cursor creation time, among
296 * other things, we assume that the only additions ever occur to the
297 * typelist.
299 krb5_error_code
300 krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *t)
302 krb5_error_code err = 0;
303 krb5_cc_typecursor n = NULL;
305 *t = NULL;
306 n = malloc(sizeof(*n));
307 if (n == NULL)
308 return ENOMEM;
310 err = k5_mutex_lock(&cc_typelist_lock);
311 if (err)
312 goto errout;
313 n->tptr = cc_typehead;
314 err = k5_mutex_unlock(&cc_typelist_lock);
315 if (err)
316 goto errout;
318 *t = n;
319 errout:
320 if (err)
321 free(n);
322 return err;
325 krb5_error_code
326 krb5int_cc_typecursor_next(
327 krb5_context context,
328 krb5_cc_typecursor t,
329 const krb5_cc_ops **ops)
331 krb5_error_code err = 0;
333 *ops = NULL;
334 if (t->tptr == NULL)
335 return 0;
337 err = k5_mutex_lock(&cc_typelist_lock);
338 if (err)
339 goto errout;
340 *ops = t->tptr->ops;
341 t->tptr = t->tptr->next;
342 err = k5_mutex_unlock(&cc_typelist_lock);
343 if (err)
344 goto errout;
346 errout:
347 return err;
350 krb5_error_code
351 krb5int_cc_typecursor_free(krb5_context context, krb5_cc_typecursor *t)
353 free(*t);
354 *t = NULL;
355 return 0;