17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * lib/krb5/ccache/ccbase.c 37c478bd9Sstevel@tonic-gate * 4505d05c7Sgtb * Copyright 1990,2004 by the Massachusetts Institute of Technology. 57c478bd9Sstevel@tonic-gate * All Rights Reserved. 67c478bd9Sstevel@tonic-gate * 77c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 87c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 97c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 107c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 11505d05c7Sgtb * 127c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 137c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 147c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 157c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 167c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 177c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 187c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 197c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 207c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 217c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 227c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 237c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 247c478bd9Sstevel@tonic-gate * or implied warranty. 25505d05c7Sgtb * 267c478bd9Sstevel@tonic-gate * 277c478bd9Sstevel@tonic-gate * Registration functions for ccache. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 30d51f1d33Smp /* 31*159d09a2SMark Phalan * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 32d51f1d33Smp * Use is subject to license terms. 33d51f1d33Smp */ 34d51f1d33Smp 35d51f1d33Smp 36505d05c7Sgtb #include "k5-int.h" 37505d05c7Sgtb #include "k5-thread.h" 38505d05c7Sgtb 39505d05c7Sgtb #include "fcc.h" 40505d05c7Sgtb #include "cc-int.h" 41505d05c7Sgtb 42505d05c7Sgtb struct krb5_cc_typelist { 43505d05c7Sgtb const krb5_cc_ops *ops; 44505d05c7Sgtb struct krb5_cc_typelist *next; 45505d05c7Sgtb }; 46*159d09a2SMark Phalan 47*159d09a2SMark Phalan struct krb5_cc_typecursor { 48*159d09a2SMark Phalan struct krb5_cc_typelist *tptr; 49*159d09a2SMark Phalan }; 50*159d09a2SMark Phalan /* typedef krb5_cc_typecursor in k5-int.h */ 51*159d09a2SMark Phalan 52505d05c7Sgtb extern const krb5_cc_ops krb5_mcc_ops; 53*159d09a2SMark Phalan #ifdef USE_KEYRING_CCACHE 54*159d09a2SMark Phalan extern const krb5_cc_ops krb5_krcc_ops; 55*159d09a2SMark Phalan #endif 567c478bd9Sstevel@tonic-gate 57505d05c7Sgtb #ifdef _WIN32 58505d05c7Sgtb extern const krb5_cc_ops krb5_lcc_ops; 59505d05c7Sgtb static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL }; 60505d05c7Sgtb static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry }; 61505d05c7Sgtb #else 62*159d09a2SMark Phalan 63*159d09a2SMark Phalan #ifdef USE_CCAPI_V3 64*159d09a2SMark Phalan extern const krb5_cc_ops krb5_cc_stdcc_ops; 65*159d09a2SMark Phalan static struct krb5_cc_typelist cc_stdcc_entry = { &krb5_cc_stdcc_ops, NULL }; 66*159d09a2SMark Phalan static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_stdcc_entry }; 67*159d09a2SMark Phalan #else 68*159d09a2SMark Phalan 69505d05c7Sgtb static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL }; 70*159d09a2SMark Phalan #endif /* USE_CCAPI_V3 */ 71*159d09a2SMark Phalan 72*159d09a2SMark Phalan #ifdef USE_KEYRING_CCACHE 73*159d09a2SMark Phalan static struct krb5_cc_typelist cc_file_entry = { &krb5_cc_file_ops, 74*159d09a2SMark Phalan &cc_mcc_entry }; 75*159d09a2SMark Phalan static struct krb5_cc_typelist cc_krcc_entry = { &krb5_krcc_ops, 76*159d09a2SMark Phalan &cc_file_entry }; 77*159d09a2SMark Phalan #endif /* USE_KEYRING_CCACHE */ 78505d05c7Sgtb #endif 797c478bd9Sstevel@tonic-gate 80505d05c7Sgtb static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops, 81505d05c7Sgtb &cc_mcc_entry }; 82*159d09a2SMark Phalan #ifdef USE_KEYRING_CCACHE 83*159d09a2SMark Phalan #define INITIAL_TYPEHEAD (&cc_krcc_entry) 84*159d09a2SMark Phalan #else 85*159d09a2SMark Phalan #define INITIAL_TYPEHEAD (&cc_fcc_entry) 86*159d09a2SMark Phalan #endif 87*159d09a2SMark Phalan static struct krb5_cc_typelist *cc_typehead = INITIAL_TYPEHEAD; 88505d05c7Sgtb static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; 89505d05c7Sgtb 90*159d09a2SMark Phalan static krb5_error_code 91*159d09a2SMark Phalan krb5int_cc_getops(krb5_context, const char *, const krb5_cc_ops **); 92*159d09a2SMark Phalan 93505d05c7Sgtb int 94505d05c7Sgtb krb5int_cc_initialize(void) 95505d05c7Sgtb { 96505d05c7Sgtb int err; 97505d05c7Sgtb 98505d05c7Sgtb err = k5_mutex_finish_init(&krb5int_mcc_mutex); 99505d05c7Sgtb if (err) 100505d05c7Sgtb return err; 101505d05c7Sgtb err = k5_mutex_finish_init(&cc_typelist_lock); 102505d05c7Sgtb if (err) 103505d05c7Sgtb return err; 104505d05c7Sgtb err = k5_mutex_finish_init(&krb5int_cc_file_mutex); 105505d05c7Sgtb if (err) 106505d05c7Sgtb return err; 107*159d09a2SMark Phalan #ifdef USE_KEYRING_CCACHE 108*159d09a2SMark Phalan err = k5_mutex_finish_init(&krb5int_krcc_mutex); 109*159d09a2SMark Phalan if (err) 110*159d09a2SMark Phalan return err; 111*159d09a2SMark Phalan #endif 112505d05c7Sgtb return 0; 113505d05c7Sgtb } 114505d05c7Sgtb 115505d05c7Sgtb void 116505d05c7Sgtb krb5int_cc_finalize(void) 117505d05c7Sgtb { 118505d05c7Sgtb struct krb5_cc_typelist *t, *t_next; 119505d05c7Sgtb k5_mutex_destroy(&cc_typelist_lock); 120505d05c7Sgtb k5_mutex_destroy(&krb5int_cc_file_mutex); 121505d05c7Sgtb k5_mutex_destroy(&krb5int_mcc_mutex); 122*159d09a2SMark Phalan #ifdef USE_KEYRING_CCACHE 123*159d09a2SMark Phalan k5_mutex_destroy(&krb5int_krcc_mutex); 124*159d09a2SMark Phalan #endif 125*159d09a2SMark Phalan for (t = cc_typehead; t != INITIAL_TYPEHEAD; t = t_next) { 126505d05c7Sgtb t_next = t->next; 127505d05c7Sgtb free(t); 128505d05c7Sgtb } 129505d05c7Sgtb } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * Register a new credentials cache type 1347c478bd9Sstevel@tonic-gate * If override is set, replace any existing ccache with that type tag 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate 137505d05c7Sgtb krb5_error_code KRB5_CALLCONV 138505d05c7Sgtb krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override) 1397c478bd9Sstevel@tonic-gate { 1407c478bd9Sstevel@tonic-gate struct krb5_cc_typelist *t; 141505d05c7Sgtb krb5_error_code err; 142505d05c7Sgtb 143505d05c7Sgtb err = k5_mutex_lock(&cc_typelist_lock); 144505d05c7Sgtb if (err) 145505d05c7Sgtb return err; 1467c478bd9Sstevel@tonic-gate for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next) 1477c478bd9Sstevel@tonic-gate ; 1487c478bd9Sstevel@tonic-gate if (t) { 1497c478bd9Sstevel@tonic-gate if (override) { 1507c478bd9Sstevel@tonic-gate t->ops = ops; 151505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1527c478bd9Sstevel@tonic-gate return 0; 153505d05c7Sgtb } else { 154505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1557c478bd9Sstevel@tonic-gate return KRB5_CC_TYPE_EXISTS; 156505d05c7Sgtb } 1577c478bd9Sstevel@tonic-gate } 158505d05c7Sgtb if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) { 159505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1607c478bd9Sstevel@tonic-gate return ENOMEM; 161505d05c7Sgtb } 1627c478bd9Sstevel@tonic-gate t->next = cc_typehead; 1637c478bd9Sstevel@tonic-gate t->ops = ops; 1647c478bd9Sstevel@tonic-gate cc_typehead = t; 165505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 1667c478bd9Sstevel@tonic-gate return 0; 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * Resolve a credential cache name into a cred. cache object. 1717c478bd9Sstevel@tonic-gate * 1727c478bd9Sstevel@tonic-gate * The name is currently constrained to be of the form "type:residual"; 1737c478bd9Sstevel@tonic-gate * 1747c478bd9Sstevel@tonic-gate * The "type" portion corresponds to one of the predefined credential 1757c478bd9Sstevel@tonic-gate * cache types, while the "residual" portion is specific to the 1767c478bd9Sstevel@tonic-gate * particular cache type. 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate 179505d05c7Sgtb #include <ctype.h> 180505d05c7Sgtb krb5_error_code KRB5_CALLCONV 181505d05c7Sgtb krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache) 1827c478bd9Sstevel@tonic-gate { 1837c478bd9Sstevel@tonic-gate char *pfx, *cp; 184505d05c7Sgtb const char *resid; 185505d05c7Sgtb unsigned int pfxlen; 186505d05c7Sgtb krb5_error_code err; 187*159d09a2SMark Phalan const krb5_cc_ops *ops; 188505d05c7Sgtb 189d51f1d33Smp /* Solaris Kerberos */ 190d51f1d33Smp if (!name) 191d51f1d33Smp return KRB5_CC_BADNAME; 192d51f1d33Smp 193*159d09a2SMark Phalan pfx = NULL; 1947c478bd9Sstevel@tonic-gate cp = strchr (name, ':'); 1957c478bd9Sstevel@tonic-gate if (!cp) { 1967c478bd9Sstevel@tonic-gate if (krb5_cc_dfl_ops) 197505d05c7Sgtb return (*krb5_cc_dfl_ops->resolve)(context, cache, name); 1987c478bd9Sstevel@tonic-gate else 1997c478bd9Sstevel@tonic-gate return KRB5_CC_BADNAME; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate pfxlen = cp - name; 2037c478bd9Sstevel@tonic-gate 204*159d09a2SMark Phalan if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) { 205*159d09a2SMark Phalan /* We found a drive letter not a prefix - use FILE */ 206*159d09a2SMark Phalan pfx = strdup("FILE"); 207505d05c7Sgtb if (!pfx) 208505d05c7Sgtb return ENOMEM; 209505d05c7Sgtb 210505d05c7Sgtb resid = name; 211505d05c7Sgtb } else { 212505d05c7Sgtb resid = name + pfxlen + 1; 213505d05c7Sgtb 214505d05c7Sgtb pfx = malloc (pfxlen+1); 215505d05c7Sgtb if (!pfx) 216505d05c7Sgtb return ENOMEM; 217505d05c7Sgtb 218505d05c7Sgtb memcpy (pfx, name, pfxlen); 219505d05c7Sgtb pfx[pfxlen] = '\0'; 220505d05c7Sgtb } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate *cache = (krb5_ccache) 0; 2237c478bd9Sstevel@tonic-gate 224*159d09a2SMark Phalan err = krb5int_cc_getops(context, pfx, &ops); 225*159d09a2SMark Phalan if (pfx != NULL) 226505d05c7Sgtb free(pfx); 227*159d09a2SMark Phalan if (err) 228505d05c7Sgtb return err; 229*159d09a2SMark Phalan 230*159d09a2SMark Phalan return ops->resolve(context, cache, resid); 231*159d09a2SMark Phalan } 232*159d09a2SMark Phalan 233*159d09a2SMark Phalan /* 234*159d09a2SMark Phalan * cc_getops 235*159d09a2SMark Phalan * 236*159d09a2SMark Phalan * Internal function to return the ops vector for a given ccache 237*159d09a2SMark Phalan * prefix string. 238*159d09a2SMark Phalan */ 239*159d09a2SMark Phalan static krb5_error_code 240*159d09a2SMark Phalan krb5int_cc_getops( 241*159d09a2SMark Phalan krb5_context context, 242*159d09a2SMark Phalan const char *pfx, 243*159d09a2SMark Phalan const krb5_cc_ops **ops) 244*159d09a2SMark Phalan { 245*159d09a2SMark Phalan krb5_error_code err; 246*159d09a2SMark Phalan struct krb5_cc_typelist *tlist; 247*159d09a2SMark Phalan 248*159d09a2SMark Phalan err = k5_mutex_lock(&cc_typelist_lock); 249*159d09a2SMark Phalan if (err) 250*159d09a2SMark Phalan return err; 251*159d09a2SMark Phalan 2527c478bd9Sstevel@tonic-gate for (tlist = cc_typehead; tlist; tlist = tlist->next) { 2537c478bd9Sstevel@tonic-gate if (strcmp (tlist->ops->prefix, pfx) == 0) { 254*159d09a2SMark Phalan *ops = tlist->ops; 255505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 256*159d09a2SMark Phalan return 0; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate } 259505d05c7Sgtb k5_mutex_unlock(&cc_typelist_lock); 2607c478bd9Sstevel@tonic-gate if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) { 261*159d09a2SMark Phalan *ops = krb5_cc_dfl_ops; 262*159d09a2SMark Phalan return 0; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate return KRB5_CC_UNKNOWN_TYPE; 2657c478bd9Sstevel@tonic-gate } 266*159d09a2SMark Phalan 267*159d09a2SMark Phalan /* 268*159d09a2SMark Phalan * cc_new_unique 269*159d09a2SMark Phalan * 270*159d09a2SMark Phalan * Generate a new unique ccache, given a ccache type and a hint 271*159d09a2SMark Phalan * string. Ignores the hint string for now. 272*159d09a2SMark Phalan */ 273*159d09a2SMark Phalan krb5_error_code KRB5_CALLCONV 274*159d09a2SMark Phalan krb5_cc_new_unique( 275*159d09a2SMark Phalan krb5_context context, 276*159d09a2SMark Phalan const char *type, 277*159d09a2SMark Phalan const char *hint, 278*159d09a2SMark Phalan krb5_ccache *id) 279*159d09a2SMark Phalan { 280*159d09a2SMark Phalan const krb5_cc_ops *ops; 281*159d09a2SMark Phalan krb5_error_code err; 282*159d09a2SMark Phalan 283*159d09a2SMark Phalan *id = NULL; 284*159d09a2SMark Phalan 285*159d09a2SMark Phalan err = krb5int_cc_getops(context, type, &ops); 286*159d09a2SMark Phalan if (err) 287*159d09a2SMark Phalan return err; 288*159d09a2SMark Phalan 289*159d09a2SMark Phalan return ops->gen_new(context, id); 290*159d09a2SMark Phalan } 291*159d09a2SMark Phalan 292*159d09a2SMark Phalan /* 293*159d09a2SMark Phalan * cc_typecursor 294*159d09a2SMark Phalan * 295*159d09a2SMark Phalan * Note: to avoid copying the typelist at cursor creation time, among 296*159d09a2SMark Phalan * other things, we assume that the only additions ever occur to the 297*159d09a2SMark Phalan * typelist. 298*159d09a2SMark Phalan */ 299*159d09a2SMark Phalan krb5_error_code 300*159d09a2SMark Phalan krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *t) 301*159d09a2SMark Phalan { 302*159d09a2SMark Phalan krb5_error_code err = 0; 303*159d09a2SMark Phalan krb5_cc_typecursor n = NULL; 304*159d09a2SMark Phalan 305*159d09a2SMark Phalan *t = NULL; 306*159d09a2SMark Phalan n = malloc(sizeof(*n)); 307*159d09a2SMark Phalan if (n == NULL) 308*159d09a2SMark Phalan return ENOMEM; 309*159d09a2SMark Phalan 310*159d09a2SMark Phalan err = k5_mutex_lock(&cc_typelist_lock); 311*159d09a2SMark Phalan if (err) 312*159d09a2SMark Phalan goto errout; 313*159d09a2SMark Phalan n->tptr = cc_typehead; 314*159d09a2SMark Phalan err = k5_mutex_unlock(&cc_typelist_lock); 315*159d09a2SMark Phalan if (err) 316*159d09a2SMark Phalan goto errout; 317*159d09a2SMark Phalan 318*159d09a2SMark Phalan *t = n; 319*159d09a2SMark Phalan errout: 320*159d09a2SMark Phalan if (err) 321*159d09a2SMark Phalan free(n); 322*159d09a2SMark Phalan return err; 323*159d09a2SMark Phalan } 324*159d09a2SMark Phalan 325*159d09a2SMark Phalan krb5_error_code 326*159d09a2SMark Phalan krb5int_cc_typecursor_next( 327*159d09a2SMark Phalan krb5_context context, 328*159d09a2SMark Phalan krb5_cc_typecursor t, 329*159d09a2SMark Phalan const krb5_cc_ops **ops) 330*159d09a2SMark Phalan { 331*159d09a2SMark Phalan krb5_error_code err = 0; 332*159d09a2SMark Phalan 333*159d09a2SMark Phalan *ops = NULL; 334*159d09a2SMark Phalan if (t->tptr == NULL) 335*159d09a2SMark Phalan return 0; 336*159d09a2SMark Phalan 337*159d09a2SMark Phalan err = k5_mutex_lock(&cc_typelist_lock); 338*159d09a2SMark Phalan if (err) 339*159d09a2SMark Phalan goto errout; 340*159d09a2SMark Phalan *ops = t->tptr->ops; 341*159d09a2SMark Phalan t->tptr = t->tptr->next; 342*159d09a2SMark Phalan err = k5_mutex_unlock(&cc_typelist_lock); 343*159d09a2SMark Phalan if (err) 344*159d09a2SMark Phalan goto errout; 345*159d09a2SMark Phalan 346*159d09a2SMark Phalan errout: 347*159d09a2SMark Phalan return err; 348*159d09a2SMark Phalan } 349*159d09a2SMark Phalan 350*159d09a2SMark Phalan krb5_error_code 351*159d09a2SMark Phalan krb5int_cc_typecursor_free(krb5_context context, krb5_cc_typecursor *t) 352*159d09a2SMark Phalan { 353*159d09a2SMark Phalan free(*t); 354*159d09a2SMark Phalan *t = NULL; 355*159d09a2SMark Phalan return 0; 356*159d09a2SMark Phalan } 357