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 * 6*505d05c7Sgtb * 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. 13*505d05c7Sgtb * 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. 27*505d05c7Sgtb * 287c478bd9Sstevel@tonic-gate * 297c478bd9Sstevel@tonic-gate * Registration functions for ccache. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 32*505d05c7Sgtb #include "k5-int.h" 33*505d05c7Sgtb #include "k5-thread.h" 34*505d05c7Sgtb 35*505d05c7Sgtb #include "fcc.h" 36*505d05c7Sgtb #include "cc-int.h" 37*505d05c7Sgtb 38*505d05c7Sgtb struct krb5_cc_typelist { 39*505d05c7Sgtb const krb5_cc_ops *ops; 40*505d05c7Sgtb struct krb5_cc_typelist *next; 41*505d05c7Sgtb }; 42*505d05c7Sgtb extern const krb5_cc_ops krb5_mcc_ops; 437c478bd9Sstevel@tonic-gate 44*505d05c7Sgtb #ifdef _WIN32 45*505d05c7Sgtb extern const krb5_cc_ops krb5_lcc_ops; 46*505d05c7Sgtb static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL }; 47*505d05c7Sgtb static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry }; 48*505d05c7Sgtb #else 49*505d05c7Sgtb static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL }; 50*505d05c7Sgtb #endif 517c478bd9Sstevel@tonic-gate 52*505d05c7Sgtb static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops, 53*505d05c7Sgtb &cc_mcc_entry }; 54*505d05c7Sgtb 55*505d05c7Sgtb static struct krb5_cc_typelist *cc_typehead = &cc_fcc_entry; 56*505d05c7Sgtb static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; 57*505d05c7Sgtb 58*505d05c7Sgtb int 59*505d05c7Sgtb krb5int_cc_initialize(void) 60*505d05c7Sgtb { 61*505d05c7Sgtb int err; 62*505d05c7Sgtb 63*505d05c7Sgtb err = k5_mutex_finish_init(&krb5int_mcc_mutex); 64*505d05c7Sgtb if (err) 65*505d05c7Sgtb return err; 66*505d05c7Sgtb err = k5_mutex_finish_init(&cc_typelist_lock); 67*505d05c7Sgtb if (err) 68*505d05c7Sgtb return err; 69*505d05c7Sgtb err = k5_mutex_finish_init(&krb5int_cc_file_mutex); 70*505d05c7Sgtb if (err) 71*505d05c7Sgtb return err; 72*505d05c7Sgtb return 0; 73*505d05c7Sgtb } 74*505d05c7Sgtb 75*505d05c7Sgtb void 76*505d05c7Sgtb krb5int_cc_finalize(void) 77*505d05c7Sgtb { 78*505d05c7Sgtb struct krb5_cc_typelist *t, *t_next; 79*505d05c7Sgtb k5_mutex_destroy(&cc_typelist_lock); 80*505d05c7Sgtb k5_mutex_destroy(&krb5int_cc_file_mutex); 81*505d05c7Sgtb k5_mutex_destroy(&krb5int_mcc_mutex); 82*505d05c7Sgtb for (t = cc_typehead; t != &cc_fcc_entry; t = t_next) { 83*505d05c7Sgtb t_next = t->next; 84*505d05c7Sgtb free(t); 85*505d05c7Sgtb } 86*505d05c7Sgtb } 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * Register a new credentials cache type 917c478bd9Sstevel@tonic-gate * If override is set, replace any existing ccache with that type tag 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate 94*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 95*505d05c7Sgtb krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override) 967c478bd9Sstevel@tonic-gate { 977c478bd9Sstevel@tonic-gate struct krb5_cc_typelist *t; 98*505d05c7Sgtb krb5_error_code err; 99*505d05c7Sgtb 100*505d05c7Sgtb err = k5_mutex_lock(&cc_typelist_lock); 101*505d05c7Sgtb if (err) 102*505d05c7Sgtb return err; 1037c478bd9Sstevel@tonic-gate for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next) 1047c478bd9Sstevel@tonic-gate ; 1057c478bd9Sstevel@tonic-gate if (t) { 1067c478bd9Sstevel@tonic-gate if (override) { 1077c478bd9Sstevel@tonic-gate t->ops = ops; 108*505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1097c478bd9Sstevel@tonic-gate return 0; 110*505d05c7Sgtb } else { 111*505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1127c478bd9Sstevel@tonic-gate return KRB5_CC_TYPE_EXISTS; 113*505d05c7Sgtb } 1147c478bd9Sstevel@tonic-gate } 115*505d05c7Sgtb if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) { 116*505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1177c478bd9Sstevel@tonic-gate return ENOMEM; 118*505d05c7Sgtb } 1197c478bd9Sstevel@tonic-gate t->next = cc_typehead; 1207c478bd9Sstevel@tonic-gate t->ops = ops; 1217c478bd9Sstevel@tonic-gate cc_typehead = t; 122*505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1237c478bd9Sstevel@tonic-gate return 0; 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Resolve a credential cache name into a cred. cache object. 1287c478bd9Sstevel@tonic-gate * 1297c478bd9Sstevel@tonic-gate * The name is currently constrained to be of the form "type:residual"; 1307c478bd9Sstevel@tonic-gate * 1317c478bd9Sstevel@tonic-gate * The "type" portion corresponds to one of the predefined credential 1327c478bd9Sstevel@tonic-gate * cache types, while the "residual" portion is specific to the 1337c478bd9Sstevel@tonic-gate * particular cache type. 1347c478bd9Sstevel@tonic-gate */ 1357c478bd9Sstevel@tonic-gate 136*505d05c7Sgtb #include <ctype.h> 137*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 138*505d05c7Sgtb krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache) 1397c478bd9Sstevel@tonic-gate { 1407c478bd9Sstevel@tonic-gate struct krb5_cc_typelist *tlist; 1417c478bd9Sstevel@tonic-gate char *pfx, *cp; 142*505d05c7Sgtb const char *resid; 143*505d05c7Sgtb unsigned int pfxlen; 144*505d05c7Sgtb krb5_error_code err; 145*505d05c7Sgtb 1467c478bd9Sstevel@tonic-gate cp = strchr (name, ':'); 1477c478bd9Sstevel@tonic-gate if (!cp) { 1487c478bd9Sstevel@tonic-gate if (krb5_cc_dfl_ops) 149*505d05c7Sgtb return (*krb5_cc_dfl_ops->resolve)(context, cache, name); 1507c478bd9Sstevel@tonic-gate else 1517c478bd9Sstevel@tonic-gate return KRB5_CC_BADNAME; 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate pfxlen = cp - name; 1557c478bd9Sstevel@tonic-gate 156*505d05c7Sgtb if ( pfxlen == 1 && isalpha(name[0]) ) { 157*505d05c7Sgtb /* We found a drive letter not a prefix - use FILE: */ 158*505d05c7Sgtb pfx = strdup("FILE:"); 159*505d05c7Sgtb if (!pfx) 160*505d05c7Sgtb return ENOMEM; 161*505d05c7Sgtb 162*505d05c7Sgtb resid = name; 163*505d05c7Sgtb } else { 164*505d05c7Sgtb resid = name + pfxlen + 1; 165*505d05c7Sgtb 166*505d05c7Sgtb pfx = malloc (pfxlen+1); 167*505d05c7Sgtb if (!pfx) 168*505d05c7Sgtb return ENOMEM; 169*505d05c7Sgtb 170*505d05c7Sgtb memcpy (pfx, name, pfxlen); 171*505d05c7Sgtb pfx[pfxlen] = '\0'; 172*505d05c7Sgtb } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate *cache = (krb5_ccache) 0; 1757c478bd9Sstevel@tonic-gate 176*505d05c7Sgtb err = k5_mutex_lock(&cc_typelist_lock); 177*505d05c7Sgtb if (err) { 178*505d05c7Sgtb free(pfx); 179*505d05c7Sgtb return err; 180*505d05c7Sgtb } 1817c478bd9Sstevel@tonic-gate for (tlist = cc_typehead; tlist; tlist = tlist->next) { 1827c478bd9Sstevel@tonic-gate if (strcmp (tlist->ops->prefix, pfx) == 0) { 183*505d05c7Sgtb krb5_error_code (KRB5_CALLCONV *ccresolver)() = tlist->ops->resolve; 184*505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1857c478bd9Sstevel@tonic-gate free(pfx); 186*505d05c7Sgtb return (*ccresolver)(context, cache, resid); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate } 189*505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1907c478bd9Sstevel@tonic-gate if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) { 1917c478bd9Sstevel@tonic-gate free (pfx); 1927c478bd9Sstevel@tonic-gate return (*krb5_cc_dfl_ops->resolve)(context, cache, resid); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate free(pfx); 1957c478bd9Sstevel@tonic-gate return KRB5_CC_UNKNOWN_TYPE; 1967c478bd9Sstevel@tonic-gate } 197