17c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27c478bd9Sstevel@tonic-gate 
37c478bd9Sstevel@tonic-gate /*
47c478bd9Sstevel@tonic-gate  * lib/krb5/ccache/ccbase.c
57c478bd9Sstevel@tonic-gate  *
6505d05c7Sgtb  * Copyright 1990,2004 by the Massachusetts Institute of Technology.
77c478bd9Sstevel@tonic-gate  * All Rights Reserved.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
107c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
117c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
127c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
13505d05c7Sgtb  *
147c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
157c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
167c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
177c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
187c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
197c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
207c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
217c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
227c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
237c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
247c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
257c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
267c478bd9Sstevel@tonic-gate  * or implied warranty.
27505d05c7Sgtb  *
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  * Registration functions for ccache.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
32*d51f1d33Smp /*
33*d51f1d33Smp  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
34*d51f1d33Smp  * Use is subject to license terms.
35*d51f1d33Smp  */
36*d51f1d33Smp 
37*d51f1d33Smp 
38505d05c7Sgtb #include "k5-int.h"
39505d05c7Sgtb #include "k5-thread.h"
40505d05c7Sgtb 
41505d05c7Sgtb #include "fcc.h"
42505d05c7Sgtb #include "cc-int.h"
43505d05c7Sgtb 
44505d05c7Sgtb struct krb5_cc_typelist {
45505d05c7Sgtb     const krb5_cc_ops *ops;
46505d05c7Sgtb     struct krb5_cc_typelist *next;
47505d05c7Sgtb };
48505d05c7Sgtb extern const krb5_cc_ops krb5_mcc_ops;
497c478bd9Sstevel@tonic-gate 
50505d05c7Sgtb #ifdef _WIN32
51505d05c7Sgtb extern const krb5_cc_ops krb5_lcc_ops;
52505d05c7Sgtb static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL };
53505d05c7Sgtb static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry };
54505d05c7Sgtb #else
55505d05c7Sgtb static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL };
56505d05c7Sgtb #endif
577c478bd9Sstevel@tonic-gate 
58505d05c7Sgtb static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops,
59505d05c7Sgtb 						&cc_mcc_entry };
60505d05c7Sgtb 
61505d05c7Sgtb static struct krb5_cc_typelist *cc_typehead = &cc_fcc_entry;
62505d05c7Sgtb static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
63505d05c7Sgtb 
64505d05c7Sgtb int
65505d05c7Sgtb krb5int_cc_initialize(void)
66505d05c7Sgtb {
67505d05c7Sgtb     int err;
68505d05c7Sgtb 
69505d05c7Sgtb     err = k5_mutex_finish_init(&krb5int_mcc_mutex);
70505d05c7Sgtb     if (err)
71505d05c7Sgtb 	return err;
72505d05c7Sgtb     err = k5_mutex_finish_init(&cc_typelist_lock);
73505d05c7Sgtb     if (err)
74505d05c7Sgtb 	return err;
75505d05c7Sgtb     err = k5_mutex_finish_init(&krb5int_cc_file_mutex);
76505d05c7Sgtb     if (err)
77505d05c7Sgtb 	return err;
78505d05c7Sgtb     return 0;
79505d05c7Sgtb }
80505d05c7Sgtb 
81505d05c7Sgtb void
82505d05c7Sgtb krb5int_cc_finalize(void)
83505d05c7Sgtb {
84505d05c7Sgtb     struct krb5_cc_typelist *t, *t_next;
85505d05c7Sgtb     k5_mutex_destroy(&cc_typelist_lock);
86505d05c7Sgtb     k5_mutex_destroy(&krb5int_cc_file_mutex);
87505d05c7Sgtb     k5_mutex_destroy(&krb5int_mcc_mutex);
88505d05c7Sgtb     for (t = cc_typehead; t != &cc_fcc_entry; t = t_next) {
89505d05c7Sgtb 	t_next = t->next;
90505d05c7Sgtb 	free(t);
91505d05c7Sgtb     }
92505d05c7Sgtb }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Register a new credentials cache type
977c478bd9Sstevel@tonic-gate  * If override is set, replace any existing ccache with that type tag
987c478bd9Sstevel@tonic-gate  */
997c478bd9Sstevel@tonic-gate 
100505d05c7Sgtb krb5_error_code KRB5_CALLCONV
101505d05c7Sgtb krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate     struct krb5_cc_typelist *t;
104505d05c7Sgtb     krb5_error_code err;
105505d05c7Sgtb 
106505d05c7Sgtb     err = k5_mutex_lock(&cc_typelist_lock);
107505d05c7Sgtb     if (err)
108505d05c7Sgtb 	return err;
1097c478bd9Sstevel@tonic-gate     for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next)
1107c478bd9Sstevel@tonic-gate 	;
1117c478bd9Sstevel@tonic-gate     if (t) {
1127c478bd9Sstevel@tonic-gate 	if (override) {
1137c478bd9Sstevel@tonic-gate 	    t->ops = ops;
114505d05c7Sgtb 	    k5_mutex_unlock(&cc_typelist_lock);
1157c478bd9Sstevel@tonic-gate 	    return 0;
116505d05c7Sgtb 	} else {
117505d05c7Sgtb 	    k5_mutex_unlock(&cc_typelist_lock);
1187c478bd9Sstevel@tonic-gate 	    return KRB5_CC_TYPE_EXISTS;
119505d05c7Sgtb 	}
1207c478bd9Sstevel@tonic-gate     }
121505d05c7Sgtb     if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) {
122505d05c7Sgtb 	k5_mutex_unlock(&cc_typelist_lock);
1237c478bd9Sstevel@tonic-gate 	return ENOMEM;
124505d05c7Sgtb     }
1257c478bd9Sstevel@tonic-gate     t->next = cc_typehead;
1267c478bd9Sstevel@tonic-gate     t->ops = ops;
1277c478bd9Sstevel@tonic-gate     cc_typehead = t;
128505d05c7Sgtb     k5_mutex_unlock(&cc_typelist_lock);
1297c478bd9Sstevel@tonic-gate     return 0;
1307c478bd9Sstevel@tonic-gate }
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate /*
1337c478bd9Sstevel@tonic-gate  * Resolve a credential cache name into a cred. cache object.
1347c478bd9Sstevel@tonic-gate  *
1357c478bd9Sstevel@tonic-gate  * The name is currently constrained to be of the form "type:residual";
1367c478bd9Sstevel@tonic-gate  *
1377c478bd9Sstevel@tonic-gate  * The "type" portion corresponds to one of the predefined credential
1387c478bd9Sstevel@tonic-gate  * cache types, while the "residual" portion is specific to the
1397c478bd9Sstevel@tonic-gate  * particular cache type.
1407c478bd9Sstevel@tonic-gate  */
1417c478bd9Sstevel@tonic-gate 
142505d05c7Sgtb #include <ctype.h>
143505d05c7Sgtb krb5_error_code KRB5_CALLCONV
144505d05c7Sgtb krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache)
1457c478bd9Sstevel@tonic-gate {
1467c478bd9Sstevel@tonic-gate     struct krb5_cc_typelist *tlist;
1477c478bd9Sstevel@tonic-gate     char *pfx, *cp;
148505d05c7Sgtb     const char *resid;
149505d05c7Sgtb     unsigned int pfxlen;
150505d05c7Sgtb     krb5_error_code err;
151505d05c7Sgtb 
152*d51f1d33Smp     /* Solaris Kerberos */
153*d51f1d33Smp     if (!name)
154*d51f1d33Smp         return KRB5_CC_BADNAME;
155*d51f1d33Smp 
1567c478bd9Sstevel@tonic-gate     cp = strchr (name, ':');
1577c478bd9Sstevel@tonic-gate     if (!cp) {
1587c478bd9Sstevel@tonic-gate 	if (krb5_cc_dfl_ops)
159505d05c7Sgtb 	    return (*krb5_cc_dfl_ops->resolve)(context, cache, name);
1607c478bd9Sstevel@tonic-gate 	else
1617c478bd9Sstevel@tonic-gate 	    return KRB5_CC_BADNAME;
1627c478bd9Sstevel@tonic-gate     }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate     pfxlen = cp - name;
1657c478bd9Sstevel@tonic-gate 
166505d05c7Sgtb     if ( pfxlen == 1 && isalpha(name[0]) ) {
167505d05c7Sgtb         /* We found a drive letter not a prefix - use FILE: */
168505d05c7Sgtb         pfx = strdup("FILE:");
169505d05c7Sgtb         if (!pfx)
170505d05c7Sgtb             return ENOMEM;
171505d05c7Sgtb 
172505d05c7Sgtb         resid = name;
173505d05c7Sgtb     } else {
174505d05c7Sgtb         resid = name + pfxlen + 1;
175505d05c7Sgtb 
176505d05c7Sgtb         pfx = malloc (pfxlen+1);
177505d05c7Sgtb         if (!pfx)
178505d05c7Sgtb             return ENOMEM;
179505d05c7Sgtb 
180505d05c7Sgtb         memcpy (pfx, name, pfxlen);
181505d05c7Sgtb         pfx[pfxlen] = '\0';
182505d05c7Sgtb     }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate     *cache = (krb5_ccache) 0;
1857c478bd9Sstevel@tonic-gate 
186505d05c7Sgtb     err = k5_mutex_lock(&cc_typelist_lock);
187505d05c7Sgtb     if (err) {
188505d05c7Sgtb 	free(pfx);
189505d05c7Sgtb 	return err;
190505d05c7Sgtb     }
1917c478bd9Sstevel@tonic-gate     for (tlist = cc_typehead; tlist; tlist = tlist->next) {
1927c478bd9Sstevel@tonic-gate 	if (strcmp (tlist->ops->prefix, pfx) == 0) {
193505d05c7Sgtb 	    krb5_error_code (KRB5_CALLCONV *ccresolver)() = tlist->ops->resolve;
194505d05c7Sgtb 	    k5_mutex_unlock(&cc_typelist_lock);
1957c478bd9Sstevel@tonic-gate 	    free(pfx);
196505d05c7Sgtb 	    return (*ccresolver)(context, cache, resid);
1977c478bd9Sstevel@tonic-gate 	}
1987c478bd9Sstevel@tonic-gate     }
199505d05c7Sgtb     k5_mutex_unlock(&cc_typelist_lock);
2007c478bd9Sstevel@tonic-gate     if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) {
2017c478bd9Sstevel@tonic-gate 	free (pfx);
2027c478bd9Sstevel@tonic-gate 	return (*krb5_cc_dfl_ops->resolve)(context, cache, resid);
2037c478bd9Sstevel@tonic-gate     }
2047c478bd9Sstevel@tonic-gate     free(pfx);
2057c478bd9Sstevel@tonic-gate     return KRB5_CC_UNKNOWN_TYPE;
2067c478bd9Sstevel@tonic-gate }
207