1178825Sdfr/* 2178825Sdfr * Copyright (c) 2005, PADL Software Pty Ltd. 3178825Sdfr * All rights reserved. 4178825Sdfr * 5233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 6233294Sstas * 7178825Sdfr * Redistribution and use in source and binary forms, with or without 8178825Sdfr * modification, are permitted provided that the following conditions 9178825Sdfr * are met: 10178825Sdfr * 11178825Sdfr * 1. Redistributions of source code must retain the above copyright 12178825Sdfr * notice, this list of conditions and the following disclaimer. 13178825Sdfr * 14178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 15178825Sdfr * notice, this list of conditions and the following disclaimer in the 16178825Sdfr * documentation and/or other materials provided with the distribution. 17178825Sdfr * 18178825Sdfr * 3. Neither the name of PADL Software nor the names of its contributors 19178825Sdfr * may be used to endorse or promote products derived from this software 20178825Sdfr * without specific prior written permission. 21178825Sdfr * 22178825Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 23178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 26178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32178825Sdfr * SUCH DAMAGE. 33178825Sdfr */ 34178825Sdfr 35178825Sdfr#include "kcm_locl.h" 36178825Sdfr 37233294SstasHEIMDAL_MUTEX ccache_mutex = HEIMDAL_MUTEX_INITIALIZER; 38233294Sstaskcm_ccache_data *ccache_head = NULL; 39233294Sstasstatic unsigned int ccache_nextid = 0; 40178825Sdfr 41178825Sdfrchar *kcm_ccache_nextid(pid_t pid, uid_t uid, gid_t gid) 42178825Sdfr{ 43178825Sdfr unsigned n; 44178825Sdfr char *name; 45178825Sdfr 46178825Sdfr HEIMDAL_MUTEX_lock(&ccache_mutex); 47178825Sdfr n = ++ccache_nextid; 48178825Sdfr HEIMDAL_MUTEX_unlock(&ccache_mutex); 49178825Sdfr 50233294Sstas asprintf(&name, "%ld:%u", (long)uid, n); 51178825Sdfr 52178825Sdfr return name; 53178825Sdfr} 54178825Sdfr 55233294Sstaskrb5_error_code 56233294Sstaskcm_ccache_resolve(krb5_context context, 57233294Sstas const char *name, 58233294Sstas kcm_ccache *ccache) 59178825Sdfr{ 60178825Sdfr kcm_ccache p; 61178825Sdfr krb5_error_code ret; 62178825Sdfr 63178825Sdfr *ccache = NULL; 64178825Sdfr 65178825Sdfr ret = KRB5_FCC_NOFILE; 66178825Sdfr 67178825Sdfr HEIMDAL_MUTEX_lock(&ccache_mutex); 68178825Sdfr 69178825Sdfr for (p = ccache_head; p != NULL; p = p->next) { 70178825Sdfr if ((p->flags & KCM_FLAGS_VALID) == 0) 71178825Sdfr continue; 72178825Sdfr if (strcmp(p->name, name) == 0) { 73178825Sdfr ret = 0; 74178825Sdfr break; 75178825Sdfr } 76178825Sdfr } 77178825Sdfr 78178825Sdfr if (ret == 0) { 79178825Sdfr kcm_retain_ccache(context, p); 80178825Sdfr *ccache = p; 81178825Sdfr } 82178825Sdfr 83178825Sdfr HEIMDAL_MUTEX_unlock(&ccache_mutex); 84178825Sdfr 85178825Sdfr return ret; 86178825Sdfr} 87178825Sdfr 88233294Sstaskrb5_error_code 89233294Sstaskcm_ccache_resolve_by_uuid(krb5_context context, 90233294Sstas kcmuuid_t uuid, 91233294Sstas kcm_ccache *ccache) 92233294Sstas{ 93233294Sstas kcm_ccache p; 94233294Sstas krb5_error_code ret; 95233294Sstas 96233294Sstas *ccache = NULL; 97233294Sstas 98233294Sstas ret = KRB5_FCC_NOFILE; 99233294Sstas 100233294Sstas HEIMDAL_MUTEX_lock(&ccache_mutex); 101233294Sstas 102233294Sstas for (p = ccache_head; p != NULL; p = p->next) { 103233294Sstas if ((p->flags & KCM_FLAGS_VALID) == 0) 104233294Sstas continue; 105247002Sdim if (memcmp(p->uuid, uuid, sizeof(kcmuuid_t)) == 0) { 106233294Sstas ret = 0; 107233294Sstas break; 108233294Sstas } 109233294Sstas } 110233294Sstas 111233294Sstas if (ret == 0) { 112233294Sstas kcm_retain_ccache(context, p); 113233294Sstas *ccache = p; 114233294Sstas } 115233294Sstas 116233294Sstas HEIMDAL_MUTEX_unlock(&ccache_mutex); 117233294Sstas 118233294Sstas return ret; 119233294Sstas} 120233294Sstas 121233294Sstaskrb5_error_code 122233294Sstaskcm_ccache_get_uuids(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *sp) 123233294Sstas{ 124233294Sstas krb5_error_code ret; 125233294Sstas kcm_ccache p; 126233294Sstas 127233294Sstas ret = KRB5_FCC_NOFILE; 128233294Sstas 129233294Sstas HEIMDAL_MUTEX_lock(&ccache_mutex); 130233294Sstas 131233294Sstas for (p = ccache_head; p != NULL; p = p->next) { 132233294Sstas if ((p->flags & KCM_FLAGS_VALID) == 0) 133233294Sstas continue; 134233294Sstas ret = kcm_access(context, client, opcode, p); 135233294Sstas if (ret) { 136233294Sstas ret = 0; 137233294Sstas continue; 138233294Sstas } 139233294Sstas krb5_storage_write(sp, p->uuid, sizeof(p->uuid)); 140233294Sstas } 141233294Sstas 142233294Sstas HEIMDAL_MUTEX_unlock(&ccache_mutex); 143233294Sstas 144233294Sstas return ret; 145233294Sstas} 146233294Sstas 147233294Sstas 148178825Sdfrkrb5_error_code kcm_debug_ccache(krb5_context context) 149178825Sdfr{ 150178825Sdfr kcm_ccache p; 151178825Sdfr 152178825Sdfr for (p = ccache_head; p != NULL; p = p->next) { 153178825Sdfr char *cpn = NULL, *spn = NULL; 154178825Sdfr int ncreds = 0; 155178825Sdfr struct kcm_creds *k; 156178825Sdfr 157178825Sdfr if ((p->flags & KCM_FLAGS_VALID) == 0) { 158178825Sdfr kcm_log(7, "cache %08x: empty slot"); 159178825Sdfr continue; 160178825Sdfr } 161178825Sdfr 162178825Sdfr KCM_ASSERT_VALID(p); 163178825Sdfr 164178825Sdfr for (k = p->creds; k != NULL; k = k->next) 165178825Sdfr ncreds++; 166178825Sdfr 167178825Sdfr if (p->client != NULL) 168178825Sdfr krb5_unparse_name(context, p->client, &cpn); 169178825Sdfr if (p->server != NULL) 170178825Sdfr krb5_unparse_name(context, p->server, &spn); 171233294Sstas 172178825Sdfr kcm_log(7, "cache %08x: name %s refcnt %d flags %04x mode %04o " 173178825Sdfr "uid %d gid %d client %s server %s ncreds %d", 174178825Sdfr p, p->name, p->refcnt, p->flags, p->mode, p->uid, p->gid, 175178825Sdfr (cpn == NULL) ? "<none>" : cpn, 176178825Sdfr (spn == NULL) ? "<none>" : spn, 177178825Sdfr ncreds); 178178825Sdfr 179178825Sdfr if (cpn != NULL) 180178825Sdfr free(cpn); 181178825Sdfr if (spn != NULL) 182178825Sdfr free(spn); 183178825Sdfr } 184178825Sdfr 185178825Sdfr return 0; 186178825Sdfr} 187178825Sdfr 188233294Sstasstatic void 189233294Sstaskcm_free_ccache_data_internal(krb5_context context, 190233294Sstas kcm_ccache_data *cache) 191178825Sdfr{ 192233294Sstas KCM_ASSERT_VALID(cache); 193233294Sstas 194233294Sstas if (cache->name != NULL) { 195233294Sstas free(cache->name); 196233294Sstas cache->name = NULL; 197233294Sstas } 198233294Sstas 199233294Sstas if (cache->flags & KCM_FLAGS_USE_KEYTAB) { 200233294Sstas krb5_kt_close(context, cache->key.keytab); 201233294Sstas cache->key.keytab = NULL; 202233294Sstas } else if (cache->flags & KCM_FLAGS_USE_CACHED_KEY) { 203233294Sstas krb5_free_keyblock_contents(context, &cache->key.keyblock); 204233294Sstas krb5_keyblock_zero(&cache->key.keyblock); 205233294Sstas } 206233294Sstas 207233294Sstas cache->flags = 0; 208233294Sstas cache->mode = 0; 209233294Sstas cache->uid = -1; 210233294Sstas cache->gid = -1; 211233294Sstas cache->session = -1; 212233294Sstas 213233294Sstas kcm_zero_ccache_data_internal(context, cache); 214233294Sstas 215233294Sstas cache->tkt_life = 0; 216233294Sstas cache->renew_life = 0; 217233294Sstas 218233294Sstas cache->next = NULL; 219233294Sstas cache->refcnt = 0; 220233294Sstas 221233294Sstas HEIMDAL_MUTEX_unlock(&cache->mutex); 222233294Sstas HEIMDAL_MUTEX_destroy(&cache->mutex); 223233294Sstas} 224233294Sstas 225233294Sstas 226233294Sstaskrb5_error_code 227233294Sstaskcm_ccache_destroy(krb5_context context, const char *name) 228233294Sstas{ 229233294Sstas kcm_ccache *p, ccache; 230178825Sdfr krb5_error_code ret; 231178825Sdfr 232178825Sdfr ret = KRB5_FCC_NOFILE; 233178825Sdfr 234178825Sdfr HEIMDAL_MUTEX_lock(&ccache_mutex); 235178825Sdfr for (p = &ccache_head; *p != NULL; p = &(*p)->next) { 236178825Sdfr if (((*p)->flags & KCM_FLAGS_VALID) == 0) 237178825Sdfr continue; 238178825Sdfr if (strcmp((*p)->name, name) == 0) { 239178825Sdfr ret = 0; 240178825Sdfr break; 241178825Sdfr } 242178825Sdfr } 243178825Sdfr if (ret) 244178825Sdfr goto out; 245178825Sdfr 246233294Sstas if ((*p)->refcnt != 1) { 247233294Sstas ret = EAGAIN; 248233294Sstas goto out; 249233294Sstas } 250178825Sdfr 251233294Sstas ccache = *p; 252233294Sstas *p = (*p)->next; 253233294Sstas kcm_free_ccache_data_internal(context, ccache); 254233294Sstas free(ccache); 255233294Sstas 256178825Sdfrout: 257178825Sdfr HEIMDAL_MUTEX_unlock(&ccache_mutex); 258178825Sdfr 259178825Sdfr return ret; 260178825Sdfr} 261178825Sdfr 262178825Sdfrstatic krb5_error_code 263178825Sdfrkcm_ccache_alloc(krb5_context context, 264178825Sdfr const char *name, 265178825Sdfr kcm_ccache *ccache) 266178825Sdfr{ 267178825Sdfr kcm_ccache slot = NULL, p; 268178825Sdfr krb5_error_code ret; 269178825Sdfr int new_slot = 0; 270178825Sdfr 271178825Sdfr *ccache = NULL; 272178825Sdfr 273178825Sdfr /* First, check for duplicates */ 274178825Sdfr HEIMDAL_MUTEX_lock(&ccache_mutex); 275178825Sdfr ret = 0; 276178825Sdfr for (p = ccache_head; p != NULL; p = p->next) { 277178825Sdfr if (p->flags & KCM_FLAGS_VALID) { 278178825Sdfr if (strcmp(p->name, name) == 0) { 279178825Sdfr ret = KRB5_CC_WRITE; 280178825Sdfr break; 281178825Sdfr } 282178825Sdfr } else if (slot == NULL) 283178825Sdfr slot = p; 284178825Sdfr } 285178825Sdfr 286178825Sdfr if (ret) 287178825Sdfr goto out; 288178825Sdfr 289178825Sdfr /* 290233294Sstas * Create an enpty slot for us. 291178825Sdfr */ 292178825Sdfr if (slot == NULL) { 293233294Sstas slot = (kcm_ccache_data *)malloc(sizeof(*slot)); 294178825Sdfr if (slot == NULL) { 295233294Sstas ret = KRB5_CC_NOMEM; 296233294Sstas goto out; 297178825Sdfr } 298233294Sstas slot->next = ccache_head; 299233294Sstas HEIMDAL_MUTEX_init(&slot->mutex); 300233294Sstas new_slot = 1; 301178825Sdfr } 302178825Sdfr 303233294Sstas RAND_bytes(slot->uuid, sizeof(slot->uuid)); 304233294Sstas 305178825Sdfr slot->name = strdup(name); 306178825Sdfr if (slot->name == NULL) { 307178825Sdfr ret = KRB5_CC_NOMEM; 308178825Sdfr goto out; 309178825Sdfr } 310178825Sdfr 311178825Sdfr slot->refcnt = 1; 312178825Sdfr slot->flags = KCM_FLAGS_VALID; 313178825Sdfr slot->mode = S_IRUSR | S_IWUSR; 314178825Sdfr slot->uid = -1; 315178825Sdfr slot->gid = -1; 316178825Sdfr slot->client = NULL; 317178825Sdfr slot->server = NULL; 318178825Sdfr slot->creds = NULL; 319178825Sdfr slot->key.keytab = NULL; 320178825Sdfr slot->tkt_life = 0; 321178825Sdfr slot->renew_life = 0; 322178825Sdfr 323178825Sdfr if (new_slot) 324178825Sdfr ccache_head = slot; 325178825Sdfr 326178825Sdfr *ccache = slot; 327178825Sdfr 328178825Sdfr HEIMDAL_MUTEX_unlock(&ccache_mutex); 329178825Sdfr return 0; 330178825Sdfr 331178825Sdfrout: 332178825Sdfr HEIMDAL_MUTEX_unlock(&ccache_mutex); 333178825Sdfr if (new_slot && slot != NULL) { 334178825Sdfr HEIMDAL_MUTEX_destroy(&slot->mutex); 335178825Sdfr free(slot); 336178825Sdfr } 337178825Sdfr return ret; 338178825Sdfr} 339178825Sdfr 340178825Sdfrkrb5_error_code 341178825Sdfrkcm_ccache_remove_creds_internal(krb5_context context, 342178825Sdfr kcm_ccache ccache) 343178825Sdfr{ 344178825Sdfr struct kcm_creds *k; 345178825Sdfr 346178825Sdfr k = ccache->creds; 347178825Sdfr while (k != NULL) { 348178825Sdfr struct kcm_creds *old; 349178825Sdfr 350178825Sdfr krb5_free_cred_contents(context, &k->cred); 351178825Sdfr old = k; 352178825Sdfr k = k->next; 353178825Sdfr free(old); 354178825Sdfr } 355178825Sdfr ccache->creds = NULL; 356178825Sdfr 357178825Sdfr return 0; 358178825Sdfr} 359178825Sdfr 360178825Sdfrkrb5_error_code 361178825Sdfrkcm_ccache_remove_creds(krb5_context context, 362178825Sdfr kcm_ccache ccache) 363178825Sdfr{ 364178825Sdfr krb5_error_code ret; 365178825Sdfr 366178825Sdfr KCM_ASSERT_VALID(ccache); 367178825Sdfr 368178825Sdfr HEIMDAL_MUTEX_lock(&ccache->mutex); 369178825Sdfr ret = kcm_ccache_remove_creds_internal(context, ccache); 370178825Sdfr HEIMDAL_MUTEX_unlock(&ccache->mutex); 371178825Sdfr 372178825Sdfr return ret; 373178825Sdfr} 374178825Sdfr 375178825Sdfrkrb5_error_code 376178825Sdfrkcm_zero_ccache_data_internal(krb5_context context, 377178825Sdfr kcm_ccache_data *cache) 378178825Sdfr{ 379178825Sdfr if (cache->client != NULL) { 380178825Sdfr krb5_free_principal(context, cache->client); 381178825Sdfr cache->client = NULL; 382178825Sdfr } 383178825Sdfr 384178825Sdfr if (cache->server != NULL) { 385178825Sdfr krb5_free_principal(context, cache->server); 386178825Sdfr cache->server = NULL; 387178825Sdfr } 388178825Sdfr 389178825Sdfr kcm_ccache_remove_creds_internal(context, cache); 390178825Sdfr 391178825Sdfr return 0; 392178825Sdfr} 393178825Sdfr 394178825Sdfrkrb5_error_code 395178825Sdfrkcm_zero_ccache_data(krb5_context context, 396178825Sdfr kcm_ccache cache) 397178825Sdfr{ 398178825Sdfr krb5_error_code ret; 399178825Sdfr 400178825Sdfr KCM_ASSERT_VALID(cache); 401178825Sdfr 402178825Sdfr HEIMDAL_MUTEX_lock(&cache->mutex); 403178825Sdfr ret = kcm_zero_ccache_data_internal(context, cache); 404178825Sdfr HEIMDAL_MUTEX_unlock(&cache->mutex); 405178825Sdfr 406178825Sdfr return ret; 407178825Sdfr} 408178825Sdfr 409178825Sdfrkrb5_error_code 410178825Sdfrkcm_retain_ccache(krb5_context context, 411178825Sdfr kcm_ccache ccache) 412178825Sdfr{ 413178825Sdfr KCM_ASSERT_VALID(ccache); 414178825Sdfr 415178825Sdfr HEIMDAL_MUTEX_lock(&ccache->mutex); 416178825Sdfr ccache->refcnt++; 417178825Sdfr HEIMDAL_MUTEX_unlock(&ccache->mutex); 418178825Sdfr 419178825Sdfr return 0; 420178825Sdfr} 421178825Sdfr 422178825Sdfrkrb5_error_code 423233294Sstaskcm_release_ccache(krb5_context context, kcm_ccache c) 424178825Sdfr{ 425178825Sdfr krb5_error_code ret = 0; 426178825Sdfr 427178825Sdfr KCM_ASSERT_VALID(c); 428178825Sdfr 429178825Sdfr HEIMDAL_MUTEX_lock(&c->mutex); 430178825Sdfr if (c->refcnt == 1) { 431233294Sstas kcm_free_ccache_data_internal(context, c); 432233294Sstas free(c); 433178825Sdfr } else { 434178825Sdfr c->refcnt--; 435178825Sdfr HEIMDAL_MUTEX_unlock(&c->mutex); 436178825Sdfr } 437178825Sdfr 438178825Sdfr return ret; 439178825Sdfr} 440178825Sdfr 441178825Sdfrkrb5_error_code 442178825Sdfrkcm_ccache_gen_new(krb5_context context, 443178825Sdfr pid_t pid, 444178825Sdfr uid_t uid, 445178825Sdfr gid_t gid, 446178825Sdfr kcm_ccache *ccache) 447178825Sdfr{ 448178825Sdfr krb5_error_code ret; 449178825Sdfr char *name; 450178825Sdfr 451178825Sdfr name = kcm_ccache_nextid(pid, uid, gid); 452178825Sdfr if (name == NULL) { 453178825Sdfr return KRB5_CC_NOMEM; 454178825Sdfr } 455178825Sdfr 456178825Sdfr ret = kcm_ccache_new(context, name, ccache); 457178825Sdfr 458178825Sdfr free(name); 459178825Sdfr return ret; 460178825Sdfr} 461178825Sdfr 462178825Sdfrkrb5_error_code 463178825Sdfrkcm_ccache_new(krb5_context context, 464178825Sdfr const char *name, 465178825Sdfr kcm_ccache *ccache) 466178825Sdfr{ 467178825Sdfr krb5_error_code ret; 468178825Sdfr 469178825Sdfr ret = kcm_ccache_alloc(context, name, ccache); 470178825Sdfr if (ret == 0) { 471178825Sdfr /* 472178825Sdfr * one reference is held by the linked list, 473178825Sdfr * one by the caller 474178825Sdfr */ 475178825Sdfr kcm_retain_ccache(context, *ccache); 476178825Sdfr } 477178825Sdfr 478178825Sdfr return ret; 479178825Sdfr} 480178825Sdfr 481178825Sdfrkrb5_error_code 482178825Sdfrkcm_ccache_destroy_if_empty(krb5_context context, 483178825Sdfr kcm_ccache ccache) 484178825Sdfr{ 485178825Sdfr krb5_error_code ret; 486178825Sdfr 487178825Sdfr KCM_ASSERT_VALID(ccache); 488233294Sstas 489178825Sdfr if (ccache->creds == NULL) { 490233294Sstas ret = kcm_ccache_destroy(context, ccache->name); 491178825Sdfr } else 492178825Sdfr ret = 0; 493178825Sdfr 494178825Sdfr return ret; 495178825Sdfr} 496178825Sdfr 497178825Sdfrkrb5_error_code 498178825Sdfrkcm_ccache_store_cred(krb5_context context, 499178825Sdfr kcm_ccache ccache, 500178825Sdfr krb5_creds *creds, 501178825Sdfr int copy) 502178825Sdfr{ 503178825Sdfr krb5_error_code ret; 504178825Sdfr krb5_creds *tmp; 505178825Sdfr 506178825Sdfr KCM_ASSERT_VALID(ccache); 507233294Sstas 508178825Sdfr HEIMDAL_MUTEX_lock(&ccache->mutex); 509178825Sdfr ret = kcm_ccache_store_cred_internal(context, ccache, creds, copy, &tmp); 510178825Sdfr HEIMDAL_MUTEX_unlock(&ccache->mutex); 511178825Sdfr 512178825Sdfr return ret; 513178825Sdfr} 514178825Sdfr 515233294Sstasstruct kcm_creds * 516233294Sstaskcm_ccache_find_cred_uuid(krb5_context context, 517233294Sstas kcm_ccache ccache, 518233294Sstas kcmuuid_t uuid) 519233294Sstas{ 520233294Sstas struct kcm_creds *c; 521233294Sstas 522233294Sstas for (c = ccache->creds; c != NULL; c = c->next) 523233294Sstas if (memcmp(c->uuid, uuid, sizeof(c->uuid)) == 0) 524233294Sstas return c; 525233294Sstas 526233294Sstas return NULL; 527233294Sstas} 528233294Sstas 529233294Sstas 530233294Sstas 531178825Sdfrkrb5_error_code 532178825Sdfrkcm_ccache_store_cred_internal(krb5_context context, 533178825Sdfr kcm_ccache ccache, 534178825Sdfr krb5_creds *creds, 535178825Sdfr int copy, 536178825Sdfr krb5_creds **credp) 537178825Sdfr{ 538178825Sdfr struct kcm_creds **c; 539178825Sdfr krb5_error_code ret; 540178825Sdfr 541178825Sdfr for (c = &ccache->creds; *c != NULL; c = &(*c)->next) 542178825Sdfr ; 543178825Sdfr 544233294Sstas *c = (struct kcm_creds *)calloc(1, sizeof(**c)); 545233294Sstas if (*c == NULL) 546178825Sdfr return KRB5_CC_NOMEM; 547178825Sdfr 548233294Sstas RAND_bytes((*c)->uuid, sizeof((*c)->uuid)); 549233294Sstas 550178825Sdfr *credp = &(*c)->cred; 551178825Sdfr 552178825Sdfr if (copy) { 553178825Sdfr ret = krb5_copy_creds_contents(context, creds, *credp); 554178825Sdfr if (ret) { 555178825Sdfr free(*c); 556178825Sdfr *c = NULL; 557178825Sdfr } 558178825Sdfr } else { 559178825Sdfr **credp = *creds; 560178825Sdfr ret = 0; 561178825Sdfr } 562178825Sdfr 563178825Sdfr return ret; 564178825Sdfr} 565178825Sdfr 566178825Sdfrkrb5_error_code 567178825Sdfrkcm_ccache_remove_cred_internal(krb5_context context, 568178825Sdfr kcm_ccache ccache, 569178825Sdfr krb5_flags whichfields, 570178825Sdfr const krb5_creds *mcreds) 571178825Sdfr{ 572178825Sdfr krb5_error_code ret; 573178825Sdfr struct kcm_creds **c; 574178825Sdfr 575178825Sdfr ret = KRB5_CC_NOTFOUND; 576178825Sdfr 577178825Sdfr for (c = &ccache->creds; *c != NULL; c = &(*c)->next) { 578178825Sdfr if (krb5_compare_creds(context, whichfields, mcreds, &(*c)->cred)) { 579233294Sstas struct kcm_creds *cred = *c; 580233294Sstas 581233294Sstas *c = cred->next; 582233294Sstas krb5_free_cred_contents(context, &cred->cred); 583233294Sstas free(cred); 584178825Sdfr ret = 0; 585233294Sstas if (*c == NULL) 586233294Sstas break; 587178825Sdfr } 588178825Sdfr } 589178825Sdfr 590178825Sdfr return ret; 591178825Sdfr} 592178825Sdfr 593178825Sdfrkrb5_error_code 594178825Sdfrkcm_ccache_remove_cred(krb5_context context, 595178825Sdfr kcm_ccache ccache, 596178825Sdfr krb5_flags whichfields, 597178825Sdfr const krb5_creds *mcreds) 598178825Sdfr{ 599178825Sdfr krb5_error_code ret; 600178825Sdfr 601178825Sdfr KCM_ASSERT_VALID(ccache); 602178825Sdfr 603178825Sdfr HEIMDAL_MUTEX_lock(&ccache->mutex); 604178825Sdfr ret = kcm_ccache_remove_cred_internal(context, ccache, whichfields, mcreds); 605178825Sdfr HEIMDAL_MUTEX_unlock(&ccache->mutex); 606178825Sdfr 607178825Sdfr return ret; 608178825Sdfr} 609178825Sdfr 610178825Sdfrkrb5_error_code 611178825Sdfrkcm_ccache_retrieve_cred_internal(krb5_context context, 612178825Sdfr kcm_ccache ccache, 613178825Sdfr krb5_flags whichfields, 614178825Sdfr const krb5_creds *mcreds, 615178825Sdfr krb5_creds **creds) 616178825Sdfr{ 617178825Sdfr krb5_boolean match; 618178825Sdfr struct kcm_creds *c; 619178825Sdfr krb5_error_code ret; 620178825Sdfr 621178825Sdfr memset(creds, 0, sizeof(*creds)); 622178825Sdfr 623178825Sdfr ret = KRB5_CC_END; 624178825Sdfr 625178825Sdfr match = FALSE; 626178825Sdfr for (c = ccache->creds; c != NULL; c = c->next) { 627178825Sdfr match = krb5_compare_creds(context, whichfields, mcreds, &c->cred); 628178825Sdfr if (match) 629178825Sdfr break; 630178825Sdfr } 631178825Sdfr 632178825Sdfr if (match) { 633178825Sdfr ret = 0; 634178825Sdfr *creds = &c->cred; 635178825Sdfr } 636178825Sdfr 637178825Sdfr return ret; 638178825Sdfr} 639178825Sdfr 640178825Sdfrkrb5_error_code 641178825Sdfrkcm_ccache_retrieve_cred(krb5_context context, 642178825Sdfr kcm_ccache ccache, 643178825Sdfr krb5_flags whichfields, 644178825Sdfr const krb5_creds *mcreds, 645178825Sdfr krb5_creds **credp) 646178825Sdfr{ 647178825Sdfr krb5_error_code ret; 648178825Sdfr 649178825Sdfr KCM_ASSERT_VALID(ccache); 650233294Sstas 651178825Sdfr HEIMDAL_MUTEX_lock(&ccache->mutex); 652178825Sdfr ret = kcm_ccache_retrieve_cred_internal(context, ccache, 653178825Sdfr whichfields, mcreds, credp); 654178825Sdfr HEIMDAL_MUTEX_unlock(&ccache->mutex); 655178825Sdfr 656178825Sdfr return ret; 657178825Sdfr} 658233294Sstas 659233294Sstaschar * 660233294Sstaskcm_ccache_first_name(kcm_client *client) 661233294Sstas{ 662233294Sstas kcm_ccache p; 663233294Sstas char *name = NULL; 664233294Sstas 665233294Sstas HEIMDAL_MUTEX_lock(&ccache_mutex); 666233294Sstas 667233294Sstas for (p = ccache_head; p != NULL; p = p->next) { 668233294Sstas if (kcm_is_same_session(client, p->uid, p->session)) 669233294Sstas break; 670233294Sstas } 671233294Sstas if (p) 672233294Sstas name = strdup(p->name); 673233294Sstas HEIMDAL_MUTEX_unlock(&ccache_mutex); 674233294Sstas return name; 675233294Sstas} 676