1*505d05c7Sgtb /* 2*505d05c7Sgtb * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3*505d05c7Sgtb * Use is subject to license terms. 4*505d05c7Sgtb */ 5*505d05c7Sgtb 6*505d05c7Sgtb #pragma ident "%Z%%M% %I% %E% SMI" 7*505d05c7Sgtb 8*505d05c7Sgtb /* 9*505d05c7Sgtb * lib/krb5/ccache/cc_memory.c 10*505d05c7Sgtb * 11*505d05c7Sgtb * Copyright 1990,1991,2000,2004 by the Massachusetts Institute of Technology. 12*505d05c7Sgtb * All Rights Reserved. 13*505d05c7Sgtb * 14*505d05c7Sgtb * Export of this software from the United States of America may 15*505d05c7Sgtb * require a specific license from the United States Government. 16*505d05c7Sgtb * It is the responsibility of any person or organization contemplating 17*505d05c7Sgtb * export to obtain such a license before exporting. 18*505d05c7Sgtb * 19*505d05c7Sgtb * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 20*505d05c7Sgtb * distribute this software and its documentation for any purpose and 21*505d05c7Sgtb * without fee is hereby granted, provided that the above copyright 22*505d05c7Sgtb * notice appear in all copies and that both that copyright notice and 23*505d05c7Sgtb * this permission notice appear in supporting documentation, and that 24*505d05c7Sgtb * the name of M.I.T. not be used in advertising or publicity pertaining 25*505d05c7Sgtb * to distribution of the software without specific, written prior 26*505d05c7Sgtb * permission. Furthermore if you modify this software you must label 27*505d05c7Sgtb * your software as modified software and not distribute it in such a 28*505d05c7Sgtb * fashion that it might be confused with the original M.I.T. software. 29*505d05c7Sgtb * M.I.T. makes no representations about the suitability of 30*505d05c7Sgtb * this software for any purpose. It is provided "as is" without express 31*505d05c7Sgtb * or implied warranty. 32*505d05c7Sgtb * 33*505d05c7Sgtb * 34*505d05c7Sgtb * implementation of memory-based credentials cache 35*505d05c7Sgtb */ 36*505d05c7Sgtb #include "k5-int.h" 37*505d05c7Sgtb #include <errno.h> 38*505d05c7Sgtb 39*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_close 40*505d05c7Sgtb (krb5_context, krb5_ccache id ); 41*505d05c7Sgtb 42*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_destroy 43*505d05c7Sgtb (krb5_context, krb5_ccache id ); 44*505d05c7Sgtb 45*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_end_seq_get 46*505d05c7Sgtb (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ); 47*505d05c7Sgtb 48*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_generate_new 49*505d05c7Sgtb (krb5_context, krb5_ccache *id ); 50*505d05c7Sgtb 51*505d05c7Sgtb static const char * KRB5_CALLCONV krb5_mcc_get_name 52*505d05c7Sgtb (krb5_context, krb5_ccache id ); 53*505d05c7Sgtb 54*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_get_principal 55*505d05c7Sgtb (krb5_context, krb5_ccache id , krb5_principal *princ ); 56*505d05c7Sgtb 57*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_initialize 58*505d05c7Sgtb (krb5_context, krb5_ccache id , krb5_principal princ ); 59*505d05c7Sgtb 60*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_next_cred 61*505d05c7Sgtb (krb5_context, 62*505d05c7Sgtb krb5_ccache id , 63*505d05c7Sgtb krb5_cc_cursor *cursor , 64*505d05c7Sgtb krb5_creds *creds ); 65*505d05c7Sgtb 66*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_resolve 67*505d05c7Sgtb (krb5_context, krb5_ccache *id , const char *residual ); 68*505d05c7Sgtb 69*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_retrieve 70*505d05c7Sgtb (krb5_context, 71*505d05c7Sgtb krb5_ccache id , 72*505d05c7Sgtb krb5_flags whichfields , 73*505d05c7Sgtb krb5_creds *mcreds , 74*505d05c7Sgtb krb5_creds *creds ); 75*505d05c7Sgtb 76*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_start_seq_get 77*505d05c7Sgtb (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ); 78*505d05c7Sgtb 79*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_store 80*505d05c7Sgtb (krb5_context, krb5_ccache id , krb5_creds *creds ); 81*505d05c7Sgtb 82*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV krb5_mcc_set_flags 83*505d05c7Sgtb (krb5_context, krb5_ccache id , krb5_flags flags ); 84*505d05c7Sgtb 85*505d05c7Sgtb extern const krb5_cc_ops krb5_mcc_ops; 86*505d05c7Sgtb extern krb5_error_code krb5_change_cache (void); 87*505d05c7Sgtb 88*505d05c7Sgtb #define KRB5_OK 0 89*505d05c7Sgtb 90*505d05c7Sgtb typedef struct _krb5_mcc_link { 91*505d05c7Sgtb struct _krb5_mcc_link *next; 92*505d05c7Sgtb krb5_creds *creds; 93*505d05c7Sgtb } krb5_mcc_link, *krb5_mcc_cursor; 94*505d05c7Sgtb 95*505d05c7Sgtb typedef struct _krb5_mcc_data { 96*505d05c7Sgtb char *name; 97*505d05c7Sgtb k5_mutex_t lock; 98*505d05c7Sgtb krb5_principal prin; 99*505d05c7Sgtb krb5_mcc_cursor link; 100*505d05c7Sgtb } krb5_mcc_data; 101*505d05c7Sgtb 102*505d05c7Sgtb typedef struct krb5_mcc_list_node { 103*505d05c7Sgtb struct krb5_mcc_list_node *next; 104*505d05c7Sgtb krb5_mcc_data *cache; 105*505d05c7Sgtb } krb5_mcc_list_node; 106*505d05c7Sgtb 107*505d05c7Sgtb k5_mutex_t krb5int_mcc_mutex = K5_MUTEX_PARTIAL_INITIALIZER; 108*505d05c7Sgtb static krb5_mcc_list_node *mcc_head = 0; 109*505d05c7Sgtb 110*505d05c7Sgtb /* 111*505d05c7Sgtb * Modifies: 112*505d05c7Sgtb * id 113*505d05c7Sgtb * 114*505d05c7Sgtb * Effects: 115*505d05c7Sgtb * Creates/refreshes the file cred cache id. If the cache exists, its 116*505d05c7Sgtb * contents are destroyed. 117*505d05c7Sgtb * 118*505d05c7Sgtb * Errors: 119*505d05c7Sgtb * system errors 120*505d05c7Sgtb * permission errors 121*505d05c7Sgtb */ 122*505d05c7Sgtb static void krb5_mcc_free (krb5_context context, krb5_ccache id); 123*505d05c7Sgtb 124*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 125*505d05c7Sgtb krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) 126*505d05c7Sgtb { 127*505d05c7Sgtb krb5_error_code ret; 128*505d05c7Sgtb 129*505d05c7Sgtb krb5_mcc_free(context, id); 130*505d05c7Sgtb ret = krb5_copy_principal(context, princ, 131*505d05c7Sgtb &((krb5_mcc_data *)id->data)->prin); 132*505d05c7Sgtb if (ret == KRB5_OK) 133*505d05c7Sgtb krb5_change_cache(); 134*505d05c7Sgtb return ret; 135*505d05c7Sgtb } 136*505d05c7Sgtb 137*505d05c7Sgtb /* 138*505d05c7Sgtb * Modifies: 139*505d05c7Sgtb * id 140*505d05c7Sgtb * 141*505d05c7Sgtb * Effects: 142*505d05c7Sgtb * Closes the file cache, invalidates the id, and frees any resources 143*505d05c7Sgtb * associated with the cache. 144*505d05c7Sgtb */ 145*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 146*505d05c7Sgtb krb5_mcc_close(krb5_context context, krb5_ccache id) 147*505d05c7Sgtb { 148*505d05c7Sgtb krb5_xfree(id); 149*505d05c7Sgtb return KRB5_OK; 150*505d05c7Sgtb } 151*505d05c7Sgtb 152*505d05c7Sgtb void 153*505d05c7Sgtb krb5_mcc_free(krb5_context context, krb5_ccache id) 154*505d05c7Sgtb { 155*505d05c7Sgtb krb5_mcc_cursor curr,next; 156*505d05c7Sgtb krb5_mcc_data *d; 157*505d05c7Sgtb 158*505d05c7Sgtb d = (krb5_mcc_data *) id->data; 159*505d05c7Sgtb for (curr = d->link; curr;) { 160*505d05c7Sgtb krb5_free_creds(context, curr->creds); 161*505d05c7Sgtb next = curr->next; 162*505d05c7Sgtb krb5_xfree(curr); 163*505d05c7Sgtb curr = next; 164*505d05c7Sgtb } 165*505d05c7Sgtb d->link = NULL; 166*505d05c7Sgtb krb5_free_principal(context, d->prin); 167*505d05c7Sgtb } 168*505d05c7Sgtb 169*505d05c7Sgtb /* 170*505d05c7Sgtb * Effects: 171*505d05c7Sgtb * Destroys the contents of id. 172*505d05c7Sgtb * 173*505d05c7Sgtb * Errors: 174*505d05c7Sgtb * none 175*505d05c7Sgtb */ 176*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 177*505d05c7Sgtb krb5_mcc_destroy(krb5_context context, krb5_ccache id) 178*505d05c7Sgtb { 179*505d05c7Sgtb krb5_mcc_list_node **curr, *node; 180*505d05c7Sgtb krb5_mcc_data *d; 181*505d05c7Sgtb krb5_error_code err; 182*505d05c7Sgtb 183*505d05c7Sgtb err = k5_mutex_lock(&krb5int_mcc_mutex); 184*505d05c7Sgtb if (err) 185*505d05c7Sgtb return err; 186*505d05c7Sgtb 187*505d05c7Sgtb d = (krb5_mcc_data *)id->data; 188*505d05c7Sgtb for (curr = &mcc_head; *curr; curr = &(*curr)->next) { 189*505d05c7Sgtb if ((*curr)->cache == d) { 190*505d05c7Sgtb node = *curr; 191*505d05c7Sgtb *curr = node->next; 192*505d05c7Sgtb free(node); 193*505d05c7Sgtb break; 194*505d05c7Sgtb } 195*505d05c7Sgtb } 196*505d05c7Sgtb k5_mutex_unlock(&krb5int_mcc_mutex); 197*505d05c7Sgtb 198*505d05c7Sgtb krb5_mcc_free(context, id); 199*505d05c7Sgtb krb5_xfree(d->name); 200*505d05c7Sgtb k5_mutex_destroy(&d->lock); 201*505d05c7Sgtb krb5_xfree(d); 202*505d05c7Sgtb krb5_xfree(id); 203*505d05c7Sgtb 204*505d05c7Sgtb krb5_change_cache (); 205*505d05c7Sgtb return KRB5_OK; 206*505d05c7Sgtb } 207*505d05c7Sgtb 208*505d05c7Sgtb /* 209*505d05c7Sgtb * Requires: 210*505d05c7Sgtb * residual is a legal path name, and a null-terminated string 211*505d05c7Sgtb * 212*505d05c7Sgtb * Modifies: 213*505d05c7Sgtb * id 214*505d05c7Sgtb * 215*505d05c7Sgtb * Effects: 216*505d05c7Sgtb * creates a file-based cred cache that will reside in the file 217*505d05c7Sgtb * residual. The cache is not opened, but the filename is reserved. 218*505d05c7Sgtb * 219*505d05c7Sgtb * Returns: 220*505d05c7Sgtb * A filled in krb5_ccache structure "id". 221*505d05c7Sgtb * 222*505d05c7Sgtb * Errors: 223*505d05c7Sgtb * KRB5_CC_NOMEM - there was insufficient memory to allocate the 224*505d05c7Sgtb * krb5_ccache. id is undefined. 225*505d05c7Sgtb * permission errors 226*505d05c7Sgtb */ 227*505d05c7Sgtb static krb5_error_code new_mcc_data (const char *, krb5_mcc_data **); 228*505d05c7Sgtb 229*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 230*505d05c7Sgtb krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual) 231*505d05c7Sgtb { 232*505d05c7Sgtb krb5_ccache lid; 233*505d05c7Sgtb krb5_mcc_list_node *ptr; 234*505d05c7Sgtb krb5_error_code err; 235*505d05c7Sgtb krb5_mcc_data *d; 236*505d05c7Sgtb 237*505d05c7Sgtb lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); 238*505d05c7Sgtb if (lid == NULL) 239*505d05c7Sgtb return KRB5_CC_NOMEM; 240*505d05c7Sgtb 241*505d05c7Sgtb lid->ops = &krb5_mcc_ops; 242*505d05c7Sgtb 243*505d05c7Sgtb err = k5_mutex_lock(&krb5int_mcc_mutex); 244*505d05c7Sgtb if (err) { 245*505d05c7Sgtb /* SUNW14resync - fix mem leak */ 246*505d05c7Sgtb krb5_xfree(lid); 247*505d05c7Sgtb return err; 248*505d05c7Sgtb } 249*505d05c7Sgtb for (ptr = mcc_head; ptr; ptr=ptr->next) 250*505d05c7Sgtb if (!strcmp(ptr->cache->name, residual)) 251*505d05c7Sgtb break; 252*505d05c7Sgtb if (ptr) 253*505d05c7Sgtb d = ptr->cache; 254*505d05c7Sgtb else { 255*505d05c7Sgtb err = new_mcc_data(residual, &d); 256*505d05c7Sgtb if (err) { 257*505d05c7Sgtb k5_mutex_unlock(&krb5int_mcc_mutex); 258*505d05c7Sgtb krb5_xfree(lid); 259*505d05c7Sgtb return err; 260*505d05c7Sgtb } 261*505d05c7Sgtb } 262*505d05c7Sgtb k5_mutex_unlock(&krb5int_mcc_mutex); 263*505d05c7Sgtb lid->data = d; 264*505d05c7Sgtb *id = lid; 265*505d05c7Sgtb return KRB5_OK; 266*505d05c7Sgtb } 267*505d05c7Sgtb 268*505d05c7Sgtb /* 269*505d05c7Sgtb * Effects: 270*505d05c7Sgtb * Prepares for a sequential search of the credentials cache. 271*505d05c7Sgtb * Returns a krb5_cc_cursor to be used with krb5_mcc_next_cred and 272*505d05c7Sgtb * krb5_mcc_end_seq_get. 273*505d05c7Sgtb * 274*505d05c7Sgtb * If the cache is modified between the time of this call and the time 275*505d05c7Sgtb * of the final krb5_mcc_end_seq_get, the results are undefined. 276*505d05c7Sgtb * 277*505d05c7Sgtb * Errors: 278*505d05c7Sgtb * KRB5_CC_NOMEM 279*505d05c7Sgtb * system errors 280*505d05c7Sgtb */ 281*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 282*505d05c7Sgtb krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id, 283*505d05c7Sgtb krb5_cc_cursor *cursor) 284*505d05c7Sgtb { 285*505d05c7Sgtb krb5_mcc_cursor mcursor; 286*505d05c7Sgtb krb5_error_code err; 287*505d05c7Sgtb krb5_mcc_data *d; 288*505d05c7Sgtb 289*505d05c7Sgtb d = id->data; 290*505d05c7Sgtb err = k5_mutex_lock(&d->lock); 291*505d05c7Sgtb if (err) 292*505d05c7Sgtb return err; 293*505d05c7Sgtb mcursor = d->link; 294*505d05c7Sgtb k5_mutex_unlock(&d->lock); 295*505d05c7Sgtb *cursor = (krb5_cc_cursor) mcursor; 296*505d05c7Sgtb return KRB5_OK; 297*505d05c7Sgtb } 298*505d05c7Sgtb 299*505d05c7Sgtb /* 300*505d05c7Sgtb * Requires: 301*505d05c7Sgtb * cursor is a krb5_cc_cursor originally obtained from 302*505d05c7Sgtb * krb5_mcc_start_seq_get. 303*505d05c7Sgtb * 304*505d05c7Sgtb * Modifes: 305*505d05c7Sgtb * cursor, creds 306*505d05c7Sgtb * 307*505d05c7Sgtb * Effects: 308*505d05c7Sgtb * Fills in creds with the "next" credentals structure from the cache 309*505d05c7Sgtb * id. The actual order the creds are returned in is arbitrary. 310*505d05c7Sgtb * Space is allocated for the variable length fields in the 311*505d05c7Sgtb * credentials structure, so the object returned must be passed to 312*505d05c7Sgtb * krb5_destroy_credential. 313*505d05c7Sgtb * 314*505d05c7Sgtb * The cursor is updated for the next call to krb5_mcc_next_cred. 315*505d05c7Sgtb * 316*505d05c7Sgtb * Errors: 317*505d05c7Sgtb * system errors 318*505d05c7Sgtb */ 319*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 320*505d05c7Sgtb krb5_mcc_next_cred(krb5_context context, krb5_ccache id, 321*505d05c7Sgtb krb5_cc_cursor *cursor, krb5_creds *creds) 322*505d05c7Sgtb { 323*505d05c7Sgtb krb5_mcc_cursor mcursor; 324*505d05c7Sgtb krb5_error_code retval; 325*505d05c7Sgtb krb5_data *scratch; 326*505d05c7Sgtb 327*505d05c7Sgtb /* Once the node in the linked list is created, it's never 328*505d05c7Sgtb modified, so we don't need to worry about locking here. (Note 329*505d05c7Sgtb that we don't support _remove_cred.) */ 330*505d05c7Sgtb mcursor = (krb5_mcc_cursor) *cursor; 331*505d05c7Sgtb if (mcursor == NULL) 332*505d05c7Sgtb return KRB5_CC_END; 333*505d05c7Sgtb memset(creds, 0, sizeof(krb5_creds)); 334*505d05c7Sgtb if (mcursor->creds) { 335*505d05c7Sgtb *creds = *mcursor->creds; 336*505d05c7Sgtb retval = krb5_copy_principal(context, mcursor->creds->client, &creds->client); 337*505d05c7Sgtb if (retval) 338*505d05c7Sgtb return retval; 339*505d05c7Sgtb retval = krb5_copy_principal(context, mcursor->creds->server, 340*505d05c7Sgtb &creds->server); 341*505d05c7Sgtb if (retval) 342*505d05c7Sgtb goto cleanclient; 343*505d05c7Sgtb retval = krb5_copy_keyblock_contents(context, &mcursor->creds->keyblock, 344*505d05c7Sgtb &creds->keyblock); 345*505d05c7Sgtb if (retval) 346*505d05c7Sgtb goto cleanserver; 347*505d05c7Sgtb retval = krb5_copy_addresses(context, mcursor->creds->addresses, 348*505d05c7Sgtb &creds->addresses); 349*505d05c7Sgtb if (retval) 350*505d05c7Sgtb goto cleanblock; 351*505d05c7Sgtb retval = krb5_copy_data(context, &mcursor->creds->ticket, &scratch); 352*505d05c7Sgtb if (retval) 353*505d05c7Sgtb goto cleanaddrs; 354*505d05c7Sgtb creds->ticket = *scratch; 355*505d05c7Sgtb krb5_xfree(scratch); 356*505d05c7Sgtb retval = krb5_copy_data(context, &mcursor->creds->second_ticket, &scratch); 357*505d05c7Sgtb if (retval) 358*505d05c7Sgtb goto cleanticket; 359*505d05c7Sgtb creds->second_ticket = *scratch; 360*505d05c7Sgtb krb5_xfree(scratch); 361*505d05c7Sgtb retval = krb5_copy_authdata(context, mcursor->creds->authdata, 362*505d05c7Sgtb &creds->authdata); 363*505d05c7Sgtb if (retval) 364*505d05c7Sgtb goto clearticket; 365*505d05c7Sgtb } 366*505d05c7Sgtb *cursor = (krb5_cc_cursor)mcursor->next; 367*505d05c7Sgtb return KRB5_OK; 368*505d05c7Sgtb 369*505d05c7Sgtb clearticket: 370*505d05c7Sgtb memset(creds->ticket.data,0, (unsigned) creds->ticket.length); 371*505d05c7Sgtb cleanticket: 372*505d05c7Sgtb krb5_xfree(creds->ticket.data); 373*505d05c7Sgtb cleanaddrs: 374*505d05c7Sgtb krb5_free_addresses(context, creds->addresses); 375*505d05c7Sgtb cleanblock: 376*505d05c7Sgtb krb5_xfree(creds->keyblock.contents); 377*505d05c7Sgtb cleanserver: 378*505d05c7Sgtb krb5_free_principal(context, creds->server); 379*505d05c7Sgtb cleanclient: 380*505d05c7Sgtb krb5_free_principal(context, creds->client); 381*505d05c7Sgtb return retval; 382*505d05c7Sgtb } 383*505d05c7Sgtb 384*505d05c7Sgtb /* 385*505d05c7Sgtb * Requires: 386*505d05c7Sgtb * cursor is a krb5_cc_cursor originally obtained from 387*505d05c7Sgtb * krb5_mcc_start_seq_get. 388*505d05c7Sgtb * 389*505d05c7Sgtb * Modifies: 390*505d05c7Sgtb * id, cursor 391*505d05c7Sgtb * 392*505d05c7Sgtb * Effects: 393*505d05c7Sgtb * Finishes sequential processing of the file credentials ccache id, 394*505d05c7Sgtb * and invalidates the cursor (it must never be used after this call). 395*505d05c7Sgtb */ 396*505d05c7Sgtb /* ARGSUSED */ 397*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 398*505d05c7Sgtb krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) 399*505d05c7Sgtb { 400*505d05c7Sgtb *cursor = 0L; 401*505d05c7Sgtb return KRB5_OK; 402*505d05c7Sgtb } 403*505d05c7Sgtb 404*505d05c7Sgtb /* Utility routine: Creates the back-end data for a memory cache, and 405*505d05c7Sgtb threads it into the global linked list. 406*505d05c7Sgtb 407*505d05c7Sgtb Call with the global list lock held. */ 408*505d05c7Sgtb static krb5_error_code 409*505d05c7Sgtb new_mcc_data (const char *name, krb5_mcc_data **dataptr) 410*505d05c7Sgtb { 411*505d05c7Sgtb krb5_error_code err; 412*505d05c7Sgtb krb5_mcc_data *d; 413*505d05c7Sgtb krb5_mcc_list_node *n; 414*505d05c7Sgtb 415*505d05c7Sgtb d = malloc(sizeof(krb5_mcc_data)); 416*505d05c7Sgtb if (d == NULL) 417*505d05c7Sgtb return KRB5_CC_NOMEM; 418*505d05c7Sgtb 419*505d05c7Sgtb err = k5_mutex_init(&d->lock); 420*505d05c7Sgtb if (err) { 421*505d05c7Sgtb krb5_xfree(d); 422*505d05c7Sgtb return err; 423*505d05c7Sgtb } 424*505d05c7Sgtb 425*505d05c7Sgtb d->name = malloc(strlen(name) + 1); 426*505d05c7Sgtb if (d->name == NULL) { 427*505d05c7Sgtb k5_mutex_destroy(&d->lock); 428*505d05c7Sgtb krb5_xfree(d); 429*505d05c7Sgtb return KRB5_CC_NOMEM; 430*505d05c7Sgtb } 431*505d05c7Sgtb d->link = NULL; 432*505d05c7Sgtb d->prin = NULL; 433*505d05c7Sgtb 434*505d05c7Sgtb /* Set up the filename */ 435*505d05c7Sgtb strcpy(d->name, name); 436*505d05c7Sgtb 437*505d05c7Sgtb n = malloc(sizeof(krb5_mcc_list_node)); 438*505d05c7Sgtb if (n == NULL) { 439*505d05c7Sgtb free(d->name); 440*505d05c7Sgtb k5_mutex_destroy(&d->lock); 441*505d05c7Sgtb free(d); 442*505d05c7Sgtb return KRB5_CC_NOMEM; 443*505d05c7Sgtb } 444*505d05c7Sgtb 445*505d05c7Sgtb n->cache = d; 446*505d05c7Sgtb n->next = mcc_head; 447*505d05c7Sgtb mcc_head = n; 448*505d05c7Sgtb 449*505d05c7Sgtb *dataptr = d; 450*505d05c7Sgtb return 0; 451*505d05c7Sgtb } 452*505d05c7Sgtb 453*505d05c7Sgtb /* 454*505d05c7Sgtb * Effects: 455*505d05c7Sgtb * Creates a new file cred cache whose name is guaranteed to be 456*505d05c7Sgtb * unique. The name begins with the string TKT_ROOT (from mcc.h). 457*505d05c7Sgtb * The cache is not opened, but the new filename is reserved. 458*505d05c7Sgtb * 459*505d05c7Sgtb * Returns: 460*505d05c7Sgtb * The filled in krb5_ccache id. 461*505d05c7Sgtb * 462*505d05c7Sgtb * Errors: 463*505d05c7Sgtb * KRB5_CC_NOMEM - there was insufficient memory to allocate the 464*505d05c7Sgtb * krb5_ccache. id is undefined. 465*505d05c7Sgtb * system errors (from open) 466*505d05c7Sgtb */ 467*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 468*505d05c7Sgtb krb5_mcc_generate_new (krb5_context context, krb5_ccache *id) 469*505d05c7Sgtb { 470*505d05c7Sgtb krb5_ccache lid; 471*505d05c7Sgtb char scratch[6+1]; /* 6 for the scratch part, +1 for NUL */ 472*505d05c7Sgtb krb5_error_code err; 473*505d05c7Sgtb krb5_mcc_data *d; 474*505d05c7Sgtb 475*505d05c7Sgtb /* Allocate memory */ 476*505d05c7Sgtb lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); 477*505d05c7Sgtb if (lid == NULL) 478*505d05c7Sgtb return KRB5_CC_NOMEM; 479*505d05c7Sgtb 480*505d05c7Sgtb lid->ops = &krb5_mcc_ops; 481*505d05c7Sgtb 482*505d05c7Sgtb (void) strcpy(scratch, "XXXXXX"); 483*505d05c7Sgtb mktemp(scratch); 484*505d05c7Sgtb 485*505d05c7Sgtb err = k5_mutex_lock(&krb5int_mcc_mutex); 486*505d05c7Sgtb if (err) { 487*505d05c7Sgtb free(lid); 488*505d05c7Sgtb return err; 489*505d05c7Sgtb } 490*505d05c7Sgtb err = new_mcc_data(scratch, &d); 491*505d05c7Sgtb k5_mutex_unlock(&krb5int_mcc_mutex); 492*505d05c7Sgtb if (err) { 493*505d05c7Sgtb krb5_xfree(lid); 494*505d05c7Sgtb return err; 495*505d05c7Sgtb } 496*505d05c7Sgtb lid->data = d; 497*505d05c7Sgtb *id = lid; /* SUNW14resync - fix to 1.4.2 */ 498*505d05c7Sgtb krb5_change_cache (); 499*505d05c7Sgtb return KRB5_OK; 500*505d05c7Sgtb } 501*505d05c7Sgtb 502*505d05c7Sgtb /* 503*505d05c7Sgtb * Requires: 504*505d05c7Sgtb * id is a file credential cache 505*505d05c7Sgtb * 506*505d05c7Sgtb * Returns: 507*505d05c7Sgtb * The name of the file cred cache id. 508*505d05c7Sgtb */ 509*505d05c7Sgtb const char * KRB5_CALLCONV 510*505d05c7Sgtb krb5_mcc_get_name (krb5_context context, krb5_ccache id) 511*505d05c7Sgtb { 512*505d05c7Sgtb return (char *) ((krb5_mcc_data *) id->data)->name; 513*505d05c7Sgtb } 514*505d05c7Sgtb 515*505d05c7Sgtb /* 516*505d05c7Sgtb * Modifies: 517*505d05c7Sgtb * id, princ 518*505d05c7Sgtb * 519*505d05c7Sgtb * Effects: 520*505d05c7Sgtb * Retrieves the primary principal from id, as set with 521*505d05c7Sgtb * krb5_mcc_initialize. The principal is returned is allocated 522*505d05c7Sgtb * storage that must be freed by the caller via krb5_free_principal. 523*505d05c7Sgtb * 524*505d05c7Sgtb * Errors: 525*505d05c7Sgtb * system errors 526*505d05c7Sgtb * KRB5_CC_NOMEM 527*505d05c7Sgtb */ 528*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 529*505d05c7Sgtb krb5_mcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *princ) 530*505d05c7Sgtb { 531*505d05c7Sgtb krb5_mcc_data *ptr = (krb5_mcc_data *)id->data; 532*505d05c7Sgtb if (!ptr->prin) { 533*505d05c7Sgtb *princ = 0L; 534*505d05c7Sgtb return KRB5_FCC_NOFILE; 535*505d05c7Sgtb } 536*505d05c7Sgtb return krb5_copy_principal(context, ptr->prin, princ); 537*505d05c7Sgtb } 538*505d05c7Sgtb 539*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 540*505d05c7Sgtb krb5_mcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, 541*505d05c7Sgtb krb5_creds *mcreds, krb5_creds *creds) 542*505d05c7Sgtb { 543*505d05c7Sgtb return krb5_cc_retrieve_cred_default (context, id, whichfields, 544*505d05c7Sgtb mcreds, creds); 545*505d05c7Sgtb } 546*505d05c7Sgtb 547*505d05c7Sgtb /* 548*505d05c7Sgtb * Non-functional stub implementation for krb5_mcc_remove 549*505d05c7Sgtb * 550*505d05c7Sgtb * Errors: 551*505d05c7Sgtb * KRB5_CC_NOSUPP - not implemented 552*505d05c7Sgtb */ 553*505d05c7Sgtb static krb5_error_code KRB5_CALLCONV 554*505d05c7Sgtb krb5_mcc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, 555*505d05c7Sgtb krb5_creds *creds) 556*505d05c7Sgtb { 557*505d05c7Sgtb return KRB5_CC_NOSUPP; 558*505d05c7Sgtb } 559*505d05c7Sgtb 560*505d05c7Sgtb 561*505d05c7Sgtb /* 562*505d05c7Sgtb * Requires: 563*505d05c7Sgtb * id is a cred cache returned by krb5_mcc_resolve or 564*505d05c7Sgtb * krb5_mcc_generate_new, but has not been opened by krb5_mcc_initialize. 565*505d05c7Sgtb * 566*505d05c7Sgtb * Modifies: 567*505d05c7Sgtb * id 568*505d05c7Sgtb * 569*505d05c7Sgtb * Effects: 570*505d05c7Sgtb * Sets the operational flags of id to flags. 571*505d05c7Sgtb */ 572*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 573*505d05c7Sgtb krb5_mcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags) 574*505d05c7Sgtb { 575*505d05c7Sgtb return KRB5_OK; 576*505d05c7Sgtb } 577*505d05c7Sgtb 578*505d05c7Sgtb /* store: Save away creds in the ccache. */ 579*505d05c7Sgtb krb5_error_code KRB5_CALLCONV 580*505d05c7Sgtb krb5_mcc_store(krb5_context ctx, krb5_ccache id, krb5_creds *creds) 581*505d05c7Sgtb { 582*505d05c7Sgtb krb5_error_code err; 583*505d05c7Sgtb krb5_mcc_link *new_node; 584*505d05c7Sgtb krb5_mcc_data *mptr = (krb5_mcc_data *)id->data; 585*505d05c7Sgtb 586*505d05c7Sgtb new_node = malloc(sizeof(krb5_mcc_link)); 587*505d05c7Sgtb if (new_node == NULL) 588*505d05c7Sgtb return errno; 589*505d05c7Sgtb err = krb5_copy_creds(ctx, creds, &new_node->creds); 590*505d05c7Sgtb if (err) { 591*505d05c7Sgtb free(new_node); 592*505d05c7Sgtb return err; 593*505d05c7Sgtb } 594*505d05c7Sgtb err = k5_mutex_lock(&mptr->lock); 595*505d05c7Sgtb if (err) { 596*505d05c7Sgtb /* SUNW14resync - fix mem leak */ 597*505d05c7Sgtb free(new_node); 598*505d05c7Sgtb return err; 599*505d05c7Sgtb } 600*505d05c7Sgtb new_node->next = mptr->link; 601*505d05c7Sgtb mptr->link = new_node; 602*505d05c7Sgtb k5_mutex_unlock(&mptr->lock); 603*505d05c7Sgtb return 0; 604*505d05c7Sgtb } 605*505d05c7Sgtb 606*505d05c7Sgtb const krb5_cc_ops krb5_mcc_ops = { 607*505d05c7Sgtb 0, 608*505d05c7Sgtb "MEMORY", 609*505d05c7Sgtb krb5_mcc_get_name, 610*505d05c7Sgtb krb5_mcc_resolve, 611*505d05c7Sgtb krb5_mcc_generate_new, 612*505d05c7Sgtb krb5_mcc_initialize, 613*505d05c7Sgtb krb5_mcc_destroy, 614*505d05c7Sgtb krb5_mcc_close, 615*505d05c7Sgtb krb5_mcc_store, 616*505d05c7Sgtb krb5_mcc_retrieve, 617*505d05c7Sgtb krb5_mcc_get_principal, 618*505d05c7Sgtb krb5_mcc_start_seq_get, 619*505d05c7Sgtb krb5_mcc_next_cred, 620*505d05c7Sgtb krb5_mcc_end_seq_get, 621*505d05c7Sgtb krb5_mcc_remove_cred, 622*505d05c7Sgtb krb5_mcc_set_flags, 623*505d05c7Sgtb }; 624