dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / gss_mechs / mech_krb5 / krb5 / ccache / ccbase.c
blob0501cc94c8a810b5c989be91d2e8586370882427
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 free(pfx);
226 if (err)
227 return err;
229 return ops->resolve(context, cache, resid);
233 * cc_getops
235 * Internal function to return the ops vector for a given ccache
236 * prefix string.
238 static krb5_error_code
239 krb5int_cc_getops(
240 krb5_context context,
241 const char *pfx,
242 const krb5_cc_ops **ops)
244 krb5_error_code err;
245 struct krb5_cc_typelist *tlist;
247 err = k5_mutex_lock(&cc_typelist_lock);
248 if (err)
249 return err;
251 for (tlist = cc_typehead; tlist; tlist = tlist->next) {
252 if (strcmp (tlist->ops->prefix, pfx) == 0) {
253 *ops = tlist->ops;
254 k5_mutex_unlock(&cc_typelist_lock);
255 return 0;
258 k5_mutex_unlock(&cc_typelist_lock);
259 if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) {
260 *ops = krb5_cc_dfl_ops;
261 return 0;
263 return KRB5_CC_UNKNOWN_TYPE;
267 * cc_new_unique
269 * Generate a new unique ccache, given a ccache type and a hint
270 * string. Ignores the hint string for now.
272 krb5_error_code KRB5_CALLCONV
273 krb5_cc_new_unique(
274 krb5_context context,
275 const char *type,
276 const char *hint,
277 krb5_ccache *id)
279 const krb5_cc_ops *ops;
280 krb5_error_code err;
282 *id = NULL;
284 err = krb5int_cc_getops(context, type, &ops);
285 if (err)
286 return err;
288 return ops->gen_new(context, id);
292 * cc_typecursor
294 * Note: to avoid copying the typelist at cursor creation time, among
295 * other things, we assume that the only additions ever occur to the
296 * typelist.
298 krb5_error_code
299 krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *t)
301 krb5_error_code err = 0;
302 krb5_cc_typecursor n = NULL;
304 *t = NULL;
305 n = malloc(sizeof(*n));
306 if (n == NULL)
307 return ENOMEM;
309 err = k5_mutex_lock(&cc_typelist_lock);
310 if (err)
311 goto errout;
312 n->tptr = cc_typehead;
313 err = k5_mutex_unlock(&cc_typelist_lock);
314 if (err)
315 goto errout;
317 *t = n;
318 errout:
319 if (err)
320 free(n);
321 return err;
324 krb5_error_code
325 krb5int_cc_typecursor_next(
326 krb5_context context,
327 krb5_cc_typecursor t,
328 const krb5_cc_ops **ops)
330 krb5_error_code err = 0;
332 *ops = NULL;
333 if (t->tptr == NULL)
334 return 0;
336 err = k5_mutex_lock(&cc_typelist_lock);
337 if (err)
338 goto errout;
339 *ops = t->tptr->ops;
340 t->tptr = t->tptr->next;
341 err = k5_mutex_unlock(&cc_typelist_lock);
342 if (err)
343 goto errout;
345 errout:
346 return err;
349 krb5_error_code
350 krb5int_cc_typecursor_free(krb5_context context, krb5_cc_typecursor *t)
352 free(*t);
353 *t = NULL;
354 return 0;