xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccbase.c (revision 7934:6aeeafc994de)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * lib/krb5/ccache/ccbase.c
30Sstevel@tonic-gate  *
4781Sgtb  * Copyright 1990,2004 by the Massachusetts Institute of Technology.
50Sstevel@tonic-gate  * All Rights Reserved.
60Sstevel@tonic-gate  *
70Sstevel@tonic-gate  * Export of this software from the United States of America may
80Sstevel@tonic-gate  *   require a specific license from the United States Government.
90Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
100Sstevel@tonic-gate  *   export to obtain such a license before exporting.
11781Sgtb  *
120Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
130Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
140Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
150Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
160Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
170Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
180Sstevel@tonic-gate  * to distribution of the software without specific, written prior
190Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
200Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
210Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
220Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
230Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
240Sstevel@tonic-gate  * or implied warranty.
25781Sgtb  *
260Sstevel@tonic-gate  *
270Sstevel@tonic-gate  * Registration functions for ccache.
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
303375Smp153739 /*
31*7934SMark.Phalan@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
323375Smp153739  * Use is subject to license terms.
333375Smp153739  */
343375Smp153739 
353375Smp153739 
36781Sgtb #include "k5-int.h"
37781Sgtb #include "k5-thread.h"
38781Sgtb 
39781Sgtb #include "fcc.h"
40781Sgtb #include "cc-int.h"
41781Sgtb 
42781Sgtb struct krb5_cc_typelist {
43781Sgtb     const krb5_cc_ops *ops;
44781Sgtb     struct krb5_cc_typelist *next;
45781Sgtb };
46*7934SMark.Phalan@Sun.COM 
47*7934SMark.Phalan@Sun.COM struct krb5_cc_typecursor {
48*7934SMark.Phalan@Sun.COM     struct krb5_cc_typelist *tptr;
49*7934SMark.Phalan@Sun.COM };
50*7934SMark.Phalan@Sun.COM /* typedef krb5_cc_typecursor in k5-int.h */
51*7934SMark.Phalan@Sun.COM 
52781Sgtb extern const krb5_cc_ops krb5_mcc_ops;
53*7934SMark.Phalan@Sun.COM #ifdef USE_KEYRING_CCACHE
54*7934SMark.Phalan@Sun.COM extern const krb5_cc_ops krb5_krcc_ops;
55*7934SMark.Phalan@Sun.COM #endif
56781Sgtb 
57781Sgtb #ifdef _WIN32
58781Sgtb extern const krb5_cc_ops krb5_lcc_ops;
59781Sgtb static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL };
60781Sgtb static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry };
61781Sgtb #else
62*7934SMark.Phalan@Sun.COM 
63*7934SMark.Phalan@Sun.COM #ifdef USE_CCAPI_V3
64*7934SMark.Phalan@Sun.COM extern const krb5_cc_ops krb5_cc_stdcc_ops;
65*7934SMark.Phalan@Sun.COM static struct krb5_cc_typelist cc_stdcc_entry = { &krb5_cc_stdcc_ops, NULL };
66*7934SMark.Phalan@Sun.COM static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_stdcc_entry };
67*7934SMark.Phalan@Sun.COM #else
68*7934SMark.Phalan@Sun.COM 
69781Sgtb static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL };
70*7934SMark.Phalan@Sun.COM #endif /* USE_CCAPI_V3 */
71*7934SMark.Phalan@Sun.COM 
72*7934SMark.Phalan@Sun.COM #ifdef USE_KEYRING_CCACHE
73*7934SMark.Phalan@Sun.COM static struct krb5_cc_typelist cc_file_entry = { &krb5_cc_file_ops,
74*7934SMark.Phalan@Sun.COM 						 &cc_mcc_entry };
75*7934SMark.Phalan@Sun.COM static struct krb5_cc_typelist cc_krcc_entry = { &krb5_krcc_ops,
76*7934SMark.Phalan@Sun.COM 						 &cc_file_entry };
77*7934SMark.Phalan@Sun.COM #endif /* USE_KEYRING_CCACHE */
78781Sgtb #endif
79781Sgtb 
80781Sgtb static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops,
81781Sgtb 						&cc_mcc_entry };
82*7934SMark.Phalan@Sun.COM #ifdef USE_KEYRING_CCACHE
83*7934SMark.Phalan@Sun.COM #define INITIAL_TYPEHEAD (&cc_krcc_entry)
84*7934SMark.Phalan@Sun.COM #else
85*7934SMark.Phalan@Sun.COM #define INITIAL_TYPEHEAD (&cc_fcc_entry)
86*7934SMark.Phalan@Sun.COM #endif
87*7934SMark.Phalan@Sun.COM static struct krb5_cc_typelist *cc_typehead = INITIAL_TYPEHEAD;
88*7934SMark.Phalan@Sun.COM static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
89781Sgtb 
90*7934SMark.Phalan@Sun.COM static krb5_error_code
91*7934SMark.Phalan@Sun.COM krb5int_cc_getops(krb5_context, const char *, const krb5_cc_ops **);
920Sstevel@tonic-gate 
93781Sgtb int
krb5int_cc_initialize(void)94781Sgtb krb5int_cc_initialize(void)
95781Sgtb {
96781Sgtb     int err;
970Sstevel@tonic-gate 
98781Sgtb     err = k5_mutex_finish_init(&krb5int_mcc_mutex);
99781Sgtb     if (err)
100781Sgtb 	return err;
101781Sgtb     err = k5_mutex_finish_init(&cc_typelist_lock);
102781Sgtb     if (err)
103781Sgtb 	return err;
104781Sgtb     err = k5_mutex_finish_init(&krb5int_cc_file_mutex);
105781Sgtb     if (err)
106781Sgtb 	return err;
107*7934SMark.Phalan@Sun.COM #ifdef USE_KEYRING_CCACHE
108*7934SMark.Phalan@Sun.COM     err = k5_mutex_finish_init(&krb5int_krcc_mutex);
109*7934SMark.Phalan@Sun.COM     if (err)
110*7934SMark.Phalan@Sun.COM 	return err;
111*7934SMark.Phalan@Sun.COM #endif
112781Sgtb     return 0;
113781Sgtb }
1140Sstevel@tonic-gate 
115781Sgtb void
krb5int_cc_finalize(void)116781Sgtb krb5int_cc_finalize(void)
117781Sgtb {
118781Sgtb     struct krb5_cc_typelist *t, *t_next;
119781Sgtb     k5_mutex_destroy(&cc_typelist_lock);
120781Sgtb     k5_mutex_destroy(&krb5int_cc_file_mutex);
121781Sgtb     k5_mutex_destroy(&krb5int_mcc_mutex);
122*7934SMark.Phalan@Sun.COM #ifdef USE_KEYRING_CCACHE
123*7934SMark.Phalan@Sun.COM     k5_mutex_destroy(&krb5int_krcc_mutex);
124*7934SMark.Phalan@Sun.COM #endif
125*7934SMark.Phalan@Sun.COM     for (t = cc_typehead; t != INITIAL_TYPEHEAD; t = t_next) {
126781Sgtb 	t_next = t->next;
127781Sgtb 	free(t);
128781Sgtb     }
129781Sgtb }
130781Sgtb 
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate /*
1330Sstevel@tonic-gate  * Register a new credentials cache type
1340Sstevel@tonic-gate  * If override is set, replace any existing ccache with that type tag
1350Sstevel@tonic-gate  */
1360Sstevel@tonic-gate 
137781Sgtb krb5_error_code KRB5_CALLCONV
krb5_cc_register(krb5_context context,krb5_cc_ops * ops,krb5_boolean override)138781Sgtb krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate     struct krb5_cc_typelist *t;
141781Sgtb     krb5_error_code err;
142781Sgtb 
143781Sgtb     err = k5_mutex_lock(&cc_typelist_lock);
144781Sgtb     if (err)
145781Sgtb 	return err;
1460Sstevel@tonic-gate     for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next)
1470Sstevel@tonic-gate 	;
1480Sstevel@tonic-gate     if (t) {
1490Sstevel@tonic-gate 	if (override) {
1500Sstevel@tonic-gate 	    t->ops = ops;
151781Sgtb 	    k5_mutex_unlock(&cc_typelist_lock);
1520Sstevel@tonic-gate 	    return 0;
153781Sgtb 	} else {
154781Sgtb 	    k5_mutex_unlock(&cc_typelist_lock);
1550Sstevel@tonic-gate 	    return KRB5_CC_TYPE_EXISTS;
156781Sgtb 	}
1570Sstevel@tonic-gate     }
158781Sgtb     if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) {
159781Sgtb 	k5_mutex_unlock(&cc_typelist_lock);
1600Sstevel@tonic-gate 	return ENOMEM;
161781Sgtb     }
1620Sstevel@tonic-gate     t->next = cc_typehead;
1630Sstevel@tonic-gate     t->ops = ops;
1640Sstevel@tonic-gate     cc_typehead = t;
165781Sgtb     k5_mutex_unlock(&cc_typelist_lock);
1660Sstevel@tonic-gate     return 0;
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * Resolve a credential cache name into a cred. cache object.
1710Sstevel@tonic-gate  *
1720Sstevel@tonic-gate  * The name is currently constrained to be of the form "type:residual";
1730Sstevel@tonic-gate  *
1740Sstevel@tonic-gate  * The "type" portion corresponds to one of the predefined credential
1750Sstevel@tonic-gate  * cache types, while the "residual" portion is specific to the
1760Sstevel@tonic-gate  * particular cache type.
1770Sstevel@tonic-gate  */
1780Sstevel@tonic-gate 
179781Sgtb #include <ctype.h>
180781Sgtb krb5_error_code KRB5_CALLCONV
krb5_cc_resolve(krb5_context context,const char * name,krb5_ccache * cache)181781Sgtb krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache)
1820Sstevel@tonic-gate {
1830Sstevel@tonic-gate     char *pfx, *cp;
184781Sgtb     const char *resid;
185781Sgtb     unsigned int pfxlen;
186781Sgtb     krb5_error_code err;
187*7934SMark.Phalan@Sun.COM     const krb5_cc_ops *ops;
188781Sgtb 
1893375Smp153739     /* Solaris Kerberos */
1903375Smp153739     if (!name)
1913375Smp153739         return KRB5_CC_BADNAME;
1923375Smp153739 
193*7934SMark.Phalan@Sun.COM     pfx = NULL;
1940Sstevel@tonic-gate     cp = strchr (name, ':');
1950Sstevel@tonic-gate     if (!cp) {
1960Sstevel@tonic-gate 	if (krb5_cc_dfl_ops)
197781Sgtb 	    return (*krb5_cc_dfl_ops->resolve)(context, cache, name);
1980Sstevel@tonic-gate 	else
1990Sstevel@tonic-gate 	    return KRB5_CC_BADNAME;
2000Sstevel@tonic-gate     }
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate     pfxlen = cp - name;
203781Sgtb 
204*7934SMark.Phalan@Sun.COM     if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) {
205*7934SMark.Phalan@Sun.COM         /* We found a drive letter not a prefix - use FILE */
206*7934SMark.Phalan@Sun.COM         pfx = strdup("FILE");
207781Sgtb         if (!pfx)
208781Sgtb             return ENOMEM;
2090Sstevel@tonic-gate 
210781Sgtb         resid = name;
211781Sgtb     } else {
212781Sgtb         resid = name + pfxlen + 1;
213781Sgtb 
214781Sgtb         pfx = malloc (pfxlen+1);
215781Sgtb         if (!pfx)
216781Sgtb             return ENOMEM;
217781Sgtb 
218781Sgtb         memcpy (pfx, name, pfxlen);
219781Sgtb         pfx[pfxlen] = '\0';
220781Sgtb     }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate     *cache = (krb5_ccache) 0;
2230Sstevel@tonic-gate 
224*7934SMark.Phalan@Sun.COM     err = krb5int_cc_getops(context, pfx, &ops);
225*7934SMark.Phalan@Sun.COM     if (pfx != NULL)
226781Sgtb 	free(pfx);
227*7934SMark.Phalan@Sun.COM     if (err)
228781Sgtb 	return err;
229*7934SMark.Phalan@Sun.COM 
230*7934SMark.Phalan@Sun.COM     return ops->resolve(context, cache, resid);
231*7934SMark.Phalan@Sun.COM }
232*7934SMark.Phalan@Sun.COM 
233*7934SMark.Phalan@Sun.COM /*
234*7934SMark.Phalan@Sun.COM  * cc_getops
235*7934SMark.Phalan@Sun.COM  *
236*7934SMark.Phalan@Sun.COM  * Internal function to return the ops vector for a given ccache
237*7934SMark.Phalan@Sun.COM  * prefix string.
238*7934SMark.Phalan@Sun.COM  */
239*7934SMark.Phalan@Sun.COM static krb5_error_code
krb5int_cc_getops(krb5_context context,const char * pfx,const krb5_cc_ops ** ops)240*7934SMark.Phalan@Sun.COM krb5int_cc_getops(
241*7934SMark.Phalan@Sun.COM     krb5_context context,
242*7934SMark.Phalan@Sun.COM     const char *pfx,
243*7934SMark.Phalan@Sun.COM     const krb5_cc_ops **ops)
244*7934SMark.Phalan@Sun.COM {
245*7934SMark.Phalan@Sun.COM     krb5_error_code err;
246*7934SMark.Phalan@Sun.COM     struct krb5_cc_typelist *tlist;
247*7934SMark.Phalan@Sun.COM 
248*7934SMark.Phalan@Sun.COM     err = k5_mutex_lock(&cc_typelist_lock);
249*7934SMark.Phalan@Sun.COM     if (err)
250*7934SMark.Phalan@Sun.COM 	return err;
251*7934SMark.Phalan@Sun.COM 
2520Sstevel@tonic-gate     for (tlist = cc_typehead; tlist; tlist = tlist->next) {
2530Sstevel@tonic-gate 	if (strcmp (tlist->ops->prefix, pfx) == 0) {
254*7934SMark.Phalan@Sun.COM 	    *ops = tlist->ops;
255781Sgtb 	    k5_mutex_unlock(&cc_typelist_lock);
256*7934SMark.Phalan@Sun.COM 	    return 0;
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate     }
259781Sgtb     k5_mutex_unlock(&cc_typelist_lock);
2600Sstevel@tonic-gate     if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) {
261*7934SMark.Phalan@Sun.COM 	*ops = krb5_cc_dfl_ops;
262*7934SMark.Phalan@Sun.COM 	return 0;
2630Sstevel@tonic-gate     }
2640Sstevel@tonic-gate     return KRB5_CC_UNKNOWN_TYPE;
2650Sstevel@tonic-gate }
266*7934SMark.Phalan@Sun.COM 
267*7934SMark.Phalan@Sun.COM /*
268*7934SMark.Phalan@Sun.COM  * cc_new_unique
269*7934SMark.Phalan@Sun.COM  *
270*7934SMark.Phalan@Sun.COM  * Generate a new unique ccache, given a ccache type and a hint
271*7934SMark.Phalan@Sun.COM  * string.  Ignores the hint string for now.
272*7934SMark.Phalan@Sun.COM  */
273*7934SMark.Phalan@Sun.COM krb5_error_code KRB5_CALLCONV
krb5_cc_new_unique(krb5_context context,const char * type,const char * hint,krb5_ccache * id)274*7934SMark.Phalan@Sun.COM krb5_cc_new_unique(
275*7934SMark.Phalan@Sun.COM     krb5_context context,
276*7934SMark.Phalan@Sun.COM     const char *type,
277*7934SMark.Phalan@Sun.COM     const char *hint,
278*7934SMark.Phalan@Sun.COM     krb5_ccache *id)
279*7934SMark.Phalan@Sun.COM {
280*7934SMark.Phalan@Sun.COM     const krb5_cc_ops *ops;
281*7934SMark.Phalan@Sun.COM     krb5_error_code err;
282*7934SMark.Phalan@Sun.COM 
283*7934SMark.Phalan@Sun.COM     *id = NULL;
284*7934SMark.Phalan@Sun.COM 
285*7934SMark.Phalan@Sun.COM     err = krb5int_cc_getops(context, type, &ops);
286*7934SMark.Phalan@Sun.COM     if (err)
287*7934SMark.Phalan@Sun.COM 	return err;
288*7934SMark.Phalan@Sun.COM 
289*7934SMark.Phalan@Sun.COM     return ops->gen_new(context, id);
290*7934SMark.Phalan@Sun.COM }
291*7934SMark.Phalan@Sun.COM 
292*7934SMark.Phalan@Sun.COM /*
293*7934SMark.Phalan@Sun.COM  * cc_typecursor
294*7934SMark.Phalan@Sun.COM  *
295*7934SMark.Phalan@Sun.COM  * Note: to avoid copying the typelist at cursor creation time, among
296*7934SMark.Phalan@Sun.COM  * other things, we assume that the only additions ever occur to the
297*7934SMark.Phalan@Sun.COM  * typelist.
298*7934SMark.Phalan@Sun.COM  */
299*7934SMark.Phalan@Sun.COM krb5_error_code
krb5int_cc_typecursor_new(krb5_context context,krb5_cc_typecursor * t)300*7934SMark.Phalan@Sun.COM krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *t)
301*7934SMark.Phalan@Sun.COM {
302*7934SMark.Phalan@Sun.COM     krb5_error_code err = 0;
303*7934SMark.Phalan@Sun.COM     krb5_cc_typecursor n = NULL;
304*7934SMark.Phalan@Sun.COM 
305*7934SMark.Phalan@Sun.COM     *t = NULL;
306*7934SMark.Phalan@Sun.COM     n = malloc(sizeof(*n));
307*7934SMark.Phalan@Sun.COM     if (n == NULL)
308*7934SMark.Phalan@Sun.COM 	return ENOMEM;
309*7934SMark.Phalan@Sun.COM 
310*7934SMark.Phalan@Sun.COM     err = k5_mutex_lock(&cc_typelist_lock);
311*7934SMark.Phalan@Sun.COM     if (err)
312*7934SMark.Phalan@Sun.COM 	goto errout;
313*7934SMark.Phalan@Sun.COM     n->tptr = cc_typehead;
314*7934SMark.Phalan@Sun.COM     err = k5_mutex_unlock(&cc_typelist_lock);
315*7934SMark.Phalan@Sun.COM     if (err)
316*7934SMark.Phalan@Sun.COM 	goto errout;
317*7934SMark.Phalan@Sun.COM 
318*7934SMark.Phalan@Sun.COM     *t = n;
319*7934SMark.Phalan@Sun.COM errout:
320*7934SMark.Phalan@Sun.COM     if (err)
321*7934SMark.Phalan@Sun.COM 	free(n);
322*7934SMark.Phalan@Sun.COM     return err;
323*7934SMark.Phalan@Sun.COM }
324*7934SMark.Phalan@Sun.COM 
325*7934SMark.Phalan@Sun.COM krb5_error_code
krb5int_cc_typecursor_next(krb5_context context,krb5_cc_typecursor t,const krb5_cc_ops ** ops)326*7934SMark.Phalan@Sun.COM krb5int_cc_typecursor_next(
327*7934SMark.Phalan@Sun.COM     krb5_context context,
328*7934SMark.Phalan@Sun.COM     krb5_cc_typecursor t,
329*7934SMark.Phalan@Sun.COM     const krb5_cc_ops **ops)
330*7934SMark.Phalan@Sun.COM {
331*7934SMark.Phalan@Sun.COM     krb5_error_code err = 0;
332*7934SMark.Phalan@Sun.COM 
333*7934SMark.Phalan@Sun.COM     *ops = NULL;
334*7934SMark.Phalan@Sun.COM     if (t->tptr == NULL)
335*7934SMark.Phalan@Sun.COM 	return 0;
336*7934SMark.Phalan@Sun.COM 
337*7934SMark.Phalan@Sun.COM     err = k5_mutex_lock(&cc_typelist_lock);
338*7934SMark.Phalan@Sun.COM     if (err)
339*7934SMark.Phalan@Sun.COM 	goto errout;
340*7934SMark.Phalan@Sun.COM     *ops = t->tptr->ops;
341*7934SMark.Phalan@Sun.COM     t->tptr = t->tptr->next;
342*7934SMark.Phalan@Sun.COM     err = k5_mutex_unlock(&cc_typelist_lock);
343*7934SMark.Phalan@Sun.COM     if (err)
344*7934SMark.Phalan@Sun.COM 	goto errout;
345*7934SMark.Phalan@Sun.COM 
346*7934SMark.Phalan@Sun.COM errout:
347*7934SMark.Phalan@Sun.COM     return err;
348*7934SMark.Phalan@Sun.COM }
349*7934SMark.Phalan@Sun.COM 
350*7934SMark.Phalan@Sun.COM krb5_error_code
krb5int_cc_typecursor_free(krb5_context context,krb5_cc_typecursor * t)351*7934SMark.Phalan@Sun.COM krb5int_cc_typecursor_free(krb5_context context, krb5_cc_typecursor *t)
352*7934SMark.Phalan@Sun.COM {
353*7934SMark.Phalan@Sun.COM     free(*t);
354*7934SMark.Phalan@Sun.COM     *t = NULL;
355*7934SMark.Phalan@Sun.COM     return 0;
356*7934SMark.Phalan@Sun.COM }
357