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 #include "k5-int.h" 33 #include "k5-thread.h" 34 35 #include "fcc.h" 36 #include "cc-int.h" 37 38 struct krb5_cc_typelist { 39 const krb5_cc_ops *ops; 40 struct krb5_cc_typelist *next; 41 }; 42 extern const krb5_cc_ops krb5_mcc_ops; 43 44 #ifdef _WIN32 45 extern const krb5_cc_ops krb5_lcc_ops; 46 static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL }; 47 static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry }; 48 #else 49 static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL }; 50 #endif 51 52 static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops, 53 &cc_mcc_entry }; 54 55 static struct krb5_cc_typelist *cc_typehead = &cc_fcc_entry; 56 static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; 57 58 int 59 krb5int_cc_initialize(void) 60 { 61 int err; 62 63 err = k5_mutex_finish_init(&krb5int_mcc_mutex); 64 if (err) 65 return err; 66 err = k5_mutex_finish_init(&cc_typelist_lock); 67 if (err) 68 return err; 69 err = k5_mutex_finish_init(&krb5int_cc_file_mutex); 70 if (err) 71 return err; 72 return 0; 73 } 74 75 void 76 krb5int_cc_finalize(void) 77 { 78 struct krb5_cc_typelist *t, *t_next; 79 k5_mutex_destroy(&cc_typelist_lock); 80 k5_mutex_destroy(&krb5int_cc_file_mutex); 81 k5_mutex_destroy(&krb5int_mcc_mutex); 82 for (t = cc_typehead; t != &cc_fcc_entry; t = t_next) { 83 t_next = t->next; 84 free(t); 85 } 86 } 87 88 89 /* 90 * Register a new credentials cache type 91 * If override is set, replace any existing ccache with that type tag 92 */ 93 94 krb5_error_code KRB5_CALLCONV 95 krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override) 96 { 97 struct krb5_cc_typelist *t; 98 krb5_error_code err; 99 100 err = k5_mutex_lock(&cc_typelist_lock); 101 if (err) 102 return err; 103 for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next) 104 ; 105 if (t) { 106 if (override) { 107 t->ops = ops; 108 k5_mutex_unlock(&cc_typelist_lock); 109 return 0; 110 } else { 111 k5_mutex_unlock(&cc_typelist_lock); 112 return KRB5_CC_TYPE_EXISTS; 113 } 114 } 115 if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) { 116 k5_mutex_unlock(&cc_typelist_lock); 117 return ENOMEM; 118 } 119 t->next = cc_typehead; 120 t->ops = ops; 121 cc_typehead = t; 122 k5_mutex_unlock(&cc_typelist_lock); 123 return 0; 124 } 125 126 /* 127 * Resolve a credential cache name into a cred. cache object. 128 * 129 * The name is currently constrained to be of the form "type:residual"; 130 * 131 * The "type" portion corresponds to one of the predefined credential 132 * cache types, while the "residual" portion is specific to the 133 * particular cache type. 134 */ 135 136 #include <ctype.h> 137 krb5_error_code KRB5_CALLCONV 138 krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache) 139 { 140 struct krb5_cc_typelist *tlist; 141 char *pfx, *cp; 142 const char *resid; 143 unsigned int pfxlen; 144 krb5_error_code err; 145 146 cp = strchr (name, ':'); 147 if (!cp) { 148 if (krb5_cc_dfl_ops) 149 return (*krb5_cc_dfl_ops->resolve)(context, cache, name); 150 else 151 return KRB5_CC_BADNAME; 152 } 153 154 pfxlen = cp - name; 155 156 if ( pfxlen == 1 && isalpha(name[0]) ) { 157 /* We found a drive letter not a prefix - use FILE: */ 158 pfx = strdup("FILE:"); 159 if (!pfx) 160 return ENOMEM; 161 162 resid = name; 163 } else { 164 resid = name + pfxlen + 1; 165 166 pfx = malloc (pfxlen+1); 167 if (!pfx) 168 return ENOMEM; 169 170 memcpy (pfx, name, pfxlen); 171 pfx[pfxlen] = '\0'; 172 } 173 174 *cache = (krb5_ccache) 0; 175 176 err = k5_mutex_lock(&cc_typelist_lock); 177 if (err) { 178 free(pfx); 179 return err; 180 } 181 for (tlist = cc_typehead; tlist; tlist = tlist->next) { 182 if (strcmp (tlist->ops->prefix, pfx) == 0) { 183 krb5_error_code (KRB5_CALLCONV *ccresolver)() = tlist->ops->resolve; 184 k5_mutex_unlock(&cc_typelist_lock); 185 free(pfx); 186 return (*ccresolver)(context, cache, resid); 187 } 188 } 189 k5_mutex_unlock(&cc_typelist_lock); 190 if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) { 191 free (pfx); 192 return (*krb5_cc_dfl_ops->resolve)(context, cache, resid); 193 } 194 free(pfx); 195 return KRB5_CC_UNKNOWN_TYPE; 196 } 197