1 #pragma ident "%Z%%M% %I% %E% SMI" 2 3 /* 4 * lib/krb5/ccache/ccbase.c 5 * 6 * Copyright 1990,2004 by the Massachusetts Institute of Technology. 7 * All Rights Reserved. 8 * 9 * Export of this software from the United States of America may 10 * require a specific license from the United States Government. 11 * It is the responsibility of any person or organization contemplating 12 * export to obtain such a license before exporting. 13 * 14 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 15 * distribute this software and its documentation for any purpose and 16 * without fee is hereby granted, provided that the above copyright 17 * notice appear in all copies and that both that copyright notice and 18 * this permission notice appear in supporting documentation, and that 19 * the name of M.I.T. not be used in advertising or publicity pertaining 20 * to distribution of the software without specific, written prior 21 * permission. Furthermore if you modify this software you must label 22 * your software as modified software and not distribute it in such a 23 * fashion that it might be confused with the original M.I.T. software. 24 * M.I.T. makes no representations about the suitability of 25 * this software for any purpose. It is provided "as is" without express 26 * or implied warranty. 27 * 28 * 29 * Registration functions for ccache. 30 */ 31 32 /* 33 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 34 * Use is subject to license terms. 35 */ 36 37 38 #include "k5-int.h" 39 #include "k5-thread.h" 40 41 #include "fcc.h" 42 #include "cc-int.h" 43 44 struct krb5_cc_typelist { 45 const krb5_cc_ops *ops; 46 struct krb5_cc_typelist *next; 47 }; 48 extern const krb5_cc_ops krb5_mcc_ops; 49 50 #ifdef _WIN32 51 extern const krb5_cc_ops krb5_lcc_ops; 52 static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL }; 53 static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry }; 54 #else 55 static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL }; 56 #endif 57 58 static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops, 59 &cc_mcc_entry }; 60 61 static struct krb5_cc_typelist *cc_typehead = &cc_fcc_entry; 62 static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; 63 64 int 65 krb5int_cc_initialize(void) 66 { 67 int err; 68 69 err = k5_mutex_finish_init(&krb5int_mcc_mutex); 70 if (err) 71 return err; 72 err = k5_mutex_finish_init(&cc_typelist_lock); 73 if (err) 74 return err; 75 err = k5_mutex_finish_init(&krb5int_cc_file_mutex); 76 if (err) 77 return err; 78 return 0; 79 } 80 81 void 82 krb5int_cc_finalize(void) 83 { 84 struct krb5_cc_typelist *t, *t_next; 85 k5_mutex_destroy(&cc_typelist_lock); 86 k5_mutex_destroy(&krb5int_cc_file_mutex); 87 k5_mutex_destroy(&krb5int_mcc_mutex); 88 for (t = cc_typehead; t != &cc_fcc_entry; t = t_next) { 89 t_next = t->next; 90 free(t); 91 } 92 } 93 94 95 /* 96 * Register a new credentials cache type 97 * If override is set, replace any existing ccache with that type tag 98 */ 99 100 krb5_error_code KRB5_CALLCONV 101 krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override) 102 { 103 struct krb5_cc_typelist *t; 104 krb5_error_code err; 105 106 err = k5_mutex_lock(&cc_typelist_lock); 107 if (err) 108 return err; 109 for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next) 110 ; 111 if (t) { 112 if (override) { 113 t->ops = ops; 114 k5_mutex_unlock(&cc_typelist_lock); 115 return 0; 116 } else { 117 k5_mutex_unlock(&cc_typelist_lock); 118 return KRB5_CC_TYPE_EXISTS; 119 } 120 } 121 if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) { 122 k5_mutex_unlock(&cc_typelist_lock); 123 return ENOMEM; 124 } 125 t->next = cc_typehead; 126 t->ops = ops; 127 cc_typehead = t; 128 k5_mutex_unlock(&cc_typelist_lock); 129 return 0; 130 } 131 132 /* 133 * Resolve a credential cache name into a cred. cache object. 134 * 135 * The name is currently constrained to be of the form "type:residual"; 136 * 137 * The "type" portion corresponds to one of the predefined credential 138 * cache types, while the "residual" portion is specific to the 139 * particular cache type. 140 */ 141 142 #include <ctype.h> 143 krb5_error_code KRB5_CALLCONV 144 krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache) 145 { 146 struct krb5_cc_typelist *tlist; 147 char *pfx, *cp; 148 const char *resid; 149 unsigned int pfxlen; 150 krb5_error_code err; 151 152 /* Solaris Kerberos */ 153 if (!name) 154 return KRB5_CC_BADNAME; 155 156 cp = strchr (name, ':'); 157 if (!cp) { 158 if (krb5_cc_dfl_ops) 159 return (*krb5_cc_dfl_ops->resolve)(context, cache, name); 160 else 161 return KRB5_CC_BADNAME; 162 } 163 164 pfxlen = cp - name; 165 166 if ( pfxlen == 1 && isalpha(name[0]) ) { 167 /* We found a drive letter not a prefix - use FILE: */ 168 pfx = strdup("FILE:"); 169 if (!pfx) 170 return ENOMEM; 171 172 resid = name; 173 } else { 174 resid = name + pfxlen + 1; 175 176 pfx = malloc (pfxlen+1); 177 if (!pfx) 178 return ENOMEM; 179 180 memcpy (pfx, name, pfxlen); 181 pfx[pfxlen] = '\0'; 182 } 183 184 *cache = (krb5_ccache) 0; 185 186 err = k5_mutex_lock(&cc_typelist_lock); 187 if (err) { 188 free(pfx); 189 return err; 190 } 191 for (tlist = cc_typehead; tlist; tlist = tlist->next) { 192 if (strcmp (tlist->ops->prefix, pfx) == 0) { 193 krb5_error_code (KRB5_CALLCONV *ccresolver)() = tlist->ops->resolve; 194 k5_mutex_unlock(&cc_typelist_lock); 195 free(pfx); 196 return (*ccresolver)(context, cache, resid); 197 } 198 } 199 k5_mutex_unlock(&cc_typelist_lock); 200 if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) { 201 free (pfx); 202 return (*krb5_cc_dfl_ops->resolve)(context, cache, resid); 203 } 204 free(pfx); 205 return KRB5_CC_UNKNOWN_TYPE; 206 } 207