1c19800e8SDoug Rabson /* 2c19800e8SDoug Rabson * Copyright (c) 2004 - 2007 Kungliga Tekniska H�gskolan 3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden). 4c19800e8SDoug Rabson * All rights reserved. 5c19800e8SDoug Rabson * 6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without 7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions 8c19800e8SDoug Rabson * are met: 9c19800e8SDoug Rabson * 10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright 11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer. 12c19800e8SDoug Rabson * 13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the 15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution. 16c19800e8SDoug Rabson * 17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors 18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software 19c19800e8SDoug Rabson * without specific prior written permission. 20c19800e8SDoug Rabson * 21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c19800e8SDoug Rabson * SUCH DAMAGE. 32c19800e8SDoug Rabson */ 33c19800e8SDoug Rabson 34c19800e8SDoug Rabson #include "krb5_locl.h" 35c19800e8SDoug Rabson #include <krb5_ccapi.h> 36c19800e8SDoug Rabson #ifdef HAVE_DLFCN_H 37c19800e8SDoug Rabson #include <dlfcn.h> 38c19800e8SDoug Rabson #endif 39c19800e8SDoug Rabson 40c19800e8SDoug Rabson RCSID("$Id: acache.c 22099 2007-12-03 17:14:34Z lha $"); 41c19800e8SDoug Rabson 42c19800e8SDoug Rabson /* XXX should we fetch these for each open ? */ 43c19800e8SDoug Rabson static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; 44c19800e8SDoug Rabson static cc_initialize_func init_func; 45c19800e8SDoug Rabson 46c19800e8SDoug Rabson #ifdef HAVE_DLOPEN 47c19800e8SDoug Rabson static void *cc_handle; 48c19800e8SDoug Rabson #endif 49c19800e8SDoug Rabson 50c19800e8SDoug Rabson typedef struct krb5_acc { 51c19800e8SDoug Rabson char *cache_name; 52c19800e8SDoug Rabson cc_context_t context; 53c19800e8SDoug Rabson cc_ccache_t ccache; 54c19800e8SDoug Rabson } krb5_acc; 55c19800e8SDoug Rabson 56c19800e8SDoug Rabson static krb5_error_code acc_close(krb5_context, krb5_ccache); 57c19800e8SDoug Rabson 58c19800e8SDoug Rabson #define ACACHE(X) ((krb5_acc *)(X)->data.data) 59c19800e8SDoug Rabson 60c19800e8SDoug Rabson static const struct { 61c19800e8SDoug Rabson cc_int32 error; 62c19800e8SDoug Rabson krb5_error_code ret; 63c19800e8SDoug Rabson } cc_errors[] = { 64c19800e8SDoug Rabson { ccErrBadName, KRB5_CC_BADNAME }, 65c19800e8SDoug Rabson { ccErrCredentialsNotFound, KRB5_CC_NOTFOUND }, 66c19800e8SDoug Rabson { ccErrCCacheNotFound, KRB5_FCC_NOFILE }, 67c19800e8SDoug Rabson { ccErrContextNotFound, KRB5_CC_NOTFOUND }, 68c19800e8SDoug Rabson { ccIteratorEnd, KRB5_CC_END }, 69c19800e8SDoug Rabson { ccErrNoMem, KRB5_CC_NOMEM }, 70c19800e8SDoug Rabson { ccErrServerUnavailable, KRB5_CC_NOSUPP }, 71c19800e8SDoug Rabson { ccNoError, 0 } 72c19800e8SDoug Rabson }; 73c19800e8SDoug Rabson 74c19800e8SDoug Rabson static krb5_error_code 75c19800e8SDoug Rabson translate_cc_error(krb5_context context, cc_int32 error) 76c19800e8SDoug Rabson { 77c19800e8SDoug Rabson int i; 78c19800e8SDoug Rabson krb5_clear_error_string(context); 79c19800e8SDoug Rabson for(i = 0; i < sizeof(cc_errors)/sizeof(cc_errors[0]); i++) 80c19800e8SDoug Rabson if (cc_errors[i].error == error) 81c19800e8SDoug Rabson return cc_errors[i].ret; 82c19800e8SDoug Rabson return KRB5_FCC_INTERNAL; 83c19800e8SDoug Rabson } 84c19800e8SDoug Rabson 85c19800e8SDoug Rabson static krb5_error_code 86c19800e8SDoug Rabson init_ccapi(krb5_context context) 87c19800e8SDoug Rabson { 88c19800e8SDoug Rabson const char *lib; 89c19800e8SDoug Rabson 90c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&acc_mutex); 91c19800e8SDoug Rabson if (init_func) { 92c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&acc_mutex); 93c19800e8SDoug Rabson krb5_clear_error_string(context); 94c19800e8SDoug Rabson return 0; 95c19800e8SDoug Rabson } 96c19800e8SDoug Rabson 97c19800e8SDoug Rabson lib = krb5_config_get_string(context, NULL, 98c19800e8SDoug Rabson "libdefaults", "ccapi_library", 99c19800e8SDoug Rabson NULL); 100c19800e8SDoug Rabson if (lib == NULL) { 101c19800e8SDoug Rabson #ifdef __APPLE__ 102c19800e8SDoug Rabson lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos"; 103c19800e8SDoug Rabson #else 104c19800e8SDoug Rabson lib = "/usr/lib/libkrb5_cc.so"; 105c19800e8SDoug Rabson #endif 106c19800e8SDoug Rabson } 107c19800e8SDoug Rabson 108c19800e8SDoug Rabson #ifdef HAVE_DLOPEN 109c19800e8SDoug Rabson 110c19800e8SDoug Rabson #ifndef RTLD_LAZY 111c19800e8SDoug Rabson #define RTLD_LAZY 0 112c19800e8SDoug Rabson #endif 113c19800e8SDoug Rabson 114c19800e8SDoug Rabson cc_handle = dlopen(lib, RTLD_LAZY); 115c19800e8SDoug Rabson if (cc_handle == NULL) { 116c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&acc_mutex); 117c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to load %s", lib); 118c19800e8SDoug Rabson return KRB5_CC_NOSUPP; 119c19800e8SDoug Rabson } 120c19800e8SDoug Rabson 121c19800e8SDoug Rabson init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize"); 122c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&acc_mutex); 123c19800e8SDoug Rabson if (init_func == NULL) { 124c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to find cc_initialize" 125c19800e8SDoug Rabson "in %s: %s", lib, dlerror()); 126c19800e8SDoug Rabson dlclose(cc_handle); 127c19800e8SDoug Rabson return KRB5_CC_NOSUPP; 128c19800e8SDoug Rabson } 129c19800e8SDoug Rabson 130c19800e8SDoug Rabson return 0; 131c19800e8SDoug Rabson #else 132c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&acc_mutex); 133c19800e8SDoug Rabson krb5_set_error_string(context, "no support for shared object"); 134c19800e8SDoug Rabson return KRB5_CC_NOSUPP; 135c19800e8SDoug Rabson #endif 136c19800e8SDoug Rabson } 137c19800e8SDoug Rabson 138c19800e8SDoug Rabson static krb5_error_code 139c19800e8SDoug Rabson make_cred_from_ccred(krb5_context context, 140c19800e8SDoug Rabson const cc_credentials_v5_t *incred, 141c19800e8SDoug Rabson krb5_creds *cred) 142c19800e8SDoug Rabson { 143c19800e8SDoug Rabson krb5_error_code ret; 144c19800e8SDoug Rabson int i; 145c19800e8SDoug Rabson 146c19800e8SDoug Rabson memset(cred, 0, sizeof(*cred)); 147c19800e8SDoug Rabson 148c19800e8SDoug Rabson ret = krb5_parse_name(context, incred->client, &cred->client); 149c19800e8SDoug Rabson if (ret) 150c19800e8SDoug Rabson goto fail; 151c19800e8SDoug Rabson 152c19800e8SDoug Rabson ret = krb5_parse_name(context, incred->server, &cred->server); 153c19800e8SDoug Rabson if (ret) 154c19800e8SDoug Rabson goto fail; 155c19800e8SDoug Rabson 156c19800e8SDoug Rabson cred->session.keytype = incred->keyblock.type; 157c19800e8SDoug Rabson cred->session.keyvalue.length = incred->keyblock.length; 158c19800e8SDoug Rabson cred->session.keyvalue.data = malloc(incred->keyblock.length); 159c19800e8SDoug Rabson if (cred->session.keyvalue.data == NULL) 160c19800e8SDoug Rabson goto nomem; 161c19800e8SDoug Rabson memcpy(cred->session.keyvalue.data, incred->keyblock.data, 162c19800e8SDoug Rabson incred->keyblock.length); 163c19800e8SDoug Rabson 164c19800e8SDoug Rabson cred->times.authtime = incred->authtime; 165c19800e8SDoug Rabson cred->times.starttime = incred->starttime; 166c19800e8SDoug Rabson cred->times.endtime = incred->endtime; 167c19800e8SDoug Rabson cred->times.renew_till = incred->renew_till; 168c19800e8SDoug Rabson 169c19800e8SDoug Rabson ret = krb5_data_copy(&cred->ticket, 170c19800e8SDoug Rabson incred->ticket.data, 171c19800e8SDoug Rabson incred->ticket.length); 172c19800e8SDoug Rabson if (ret) 173c19800e8SDoug Rabson goto nomem; 174c19800e8SDoug Rabson 175c19800e8SDoug Rabson ret = krb5_data_copy(&cred->second_ticket, 176c19800e8SDoug Rabson incred->second_ticket.data, 177c19800e8SDoug Rabson incred->second_ticket.length); 178c19800e8SDoug Rabson if (ret) 179c19800e8SDoug Rabson goto nomem; 180c19800e8SDoug Rabson 181c19800e8SDoug Rabson cred->authdata.val = NULL; 182c19800e8SDoug Rabson cred->authdata.len = 0; 183c19800e8SDoug Rabson 184c19800e8SDoug Rabson cred->addresses.val = NULL; 185c19800e8SDoug Rabson cred->addresses.len = 0; 186c19800e8SDoug Rabson 187c19800e8SDoug Rabson for (i = 0; incred->authdata && incred->authdata[i]; i++) 188c19800e8SDoug Rabson ; 189c19800e8SDoug Rabson 190c19800e8SDoug Rabson if (i) { 191c19800e8SDoug Rabson cred->authdata.val = calloc(i, sizeof(cred->authdata.val[0])); 192c19800e8SDoug Rabson if (cred->authdata.val == NULL) 193c19800e8SDoug Rabson goto nomem; 194c19800e8SDoug Rabson cred->authdata.len = i; 195c19800e8SDoug Rabson for (i = 0; i < cred->authdata.len; i++) { 196c19800e8SDoug Rabson cred->authdata.val[i].ad_type = incred->authdata[i]->type; 197c19800e8SDoug Rabson ret = krb5_data_copy(&cred->authdata.val[i].ad_data, 198c19800e8SDoug Rabson incred->authdata[i]->data, 199c19800e8SDoug Rabson incred->authdata[i]->length); 200c19800e8SDoug Rabson if (ret) 201c19800e8SDoug Rabson goto nomem; 202c19800e8SDoug Rabson } 203c19800e8SDoug Rabson } 204c19800e8SDoug Rabson 205c19800e8SDoug Rabson for (i = 0; incred->addresses && incred->addresses[i]; i++) 206c19800e8SDoug Rabson ; 207c19800e8SDoug Rabson 208c19800e8SDoug Rabson if (i) { 209c19800e8SDoug Rabson cred->addresses.val = calloc(i, sizeof(cred->addresses.val[0])); 210c19800e8SDoug Rabson if (cred->addresses.val == NULL) 211c19800e8SDoug Rabson goto nomem; 212c19800e8SDoug Rabson cred->addresses.len = i; 213c19800e8SDoug Rabson 214c19800e8SDoug Rabson for (i = 0; i < cred->addresses.len; i++) { 215c19800e8SDoug Rabson cred->addresses.val[i].addr_type = incred->addresses[i]->type; 216c19800e8SDoug Rabson ret = krb5_data_copy(&cred->addresses.val[i].address, 217c19800e8SDoug Rabson incred->addresses[i]->data, 218c19800e8SDoug Rabson incred->addresses[i]->length); 219c19800e8SDoug Rabson if (ret) 220c19800e8SDoug Rabson goto nomem; 221c19800e8SDoug Rabson } 222c19800e8SDoug Rabson } 223c19800e8SDoug Rabson 224c19800e8SDoug Rabson cred->flags.i = 0; 225c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDABLE) 226c19800e8SDoug Rabson cred->flags.b.forwardable = 1; 227c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDED) 228c19800e8SDoug Rabson cred->flags.b.forwarded = 1; 229c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXIABLE) 230c19800e8SDoug Rabson cred->flags.b.proxiable = 1; 231c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXY) 232c19800e8SDoug Rabson cred->flags.b.proxy = 1; 233c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_MAY_POSTDATE) 234c19800e8SDoug Rabson cred->flags.b.may_postdate = 1; 235c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_POSTDATED) 236c19800e8SDoug Rabson cred->flags.b.postdated = 1; 237c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INVALID) 238c19800e8SDoug Rabson cred->flags.b.invalid = 1; 239c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_RENEWABLE) 240c19800e8SDoug Rabson cred->flags.b.renewable = 1; 241c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INITIAL) 242c19800e8SDoug Rabson cred->flags.b.initial = 1; 243c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PRE_AUTH) 244c19800e8SDoug Rabson cred->flags.b.pre_authent = 1; 245c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_HW_AUTH) 246c19800e8SDoug Rabson cred->flags.b.hw_authent = 1; 247c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED) 248c19800e8SDoug Rabson cred->flags.b.transited_policy_checked = 1; 249c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE) 250c19800e8SDoug Rabson cred->flags.b.ok_as_delegate = 1; 251c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_ANONYMOUS) 252c19800e8SDoug Rabson cred->flags.b.anonymous = 1; 253c19800e8SDoug Rabson 254c19800e8SDoug Rabson return 0; 255c19800e8SDoug Rabson 256c19800e8SDoug Rabson nomem: 257c19800e8SDoug Rabson ret = ENOMEM; 258c19800e8SDoug Rabson krb5_set_error_string(context, "malloc - out of memory"); 259c19800e8SDoug Rabson 260c19800e8SDoug Rabson fail: 261c19800e8SDoug Rabson krb5_free_cred_contents(context, cred); 262c19800e8SDoug Rabson return ret; 263c19800e8SDoug Rabson } 264c19800e8SDoug Rabson 265c19800e8SDoug Rabson static void 266c19800e8SDoug Rabson free_ccred(cc_credentials_v5_t *cred) 267c19800e8SDoug Rabson { 268c19800e8SDoug Rabson int i; 269c19800e8SDoug Rabson 270c19800e8SDoug Rabson if (cred->addresses) { 271c19800e8SDoug Rabson for (i = 0; cred->addresses[i] != 0; i++) { 272c19800e8SDoug Rabson if (cred->addresses[i]->data) 273c19800e8SDoug Rabson free(cred->addresses[i]->data); 274c19800e8SDoug Rabson free(cred->addresses[i]); 275c19800e8SDoug Rabson } 276c19800e8SDoug Rabson free(cred->addresses); 277c19800e8SDoug Rabson } 278c19800e8SDoug Rabson if (cred->server) 279c19800e8SDoug Rabson free(cred->server); 280c19800e8SDoug Rabson if (cred->client) 281c19800e8SDoug Rabson free(cred->client); 282c19800e8SDoug Rabson memset(cred, 0, sizeof(*cred)); 283c19800e8SDoug Rabson } 284c19800e8SDoug Rabson 285c19800e8SDoug Rabson static krb5_error_code 286c19800e8SDoug Rabson make_ccred_from_cred(krb5_context context, 287c19800e8SDoug Rabson const krb5_creds *incred, 288c19800e8SDoug Rabson cc_credentials_v5_t *cred) 289c19800e8SDoug Rabson { 290c19800e8SDoug Rabson krb5_error_code ret; 291c19800e8SDoug Rabson int i; 292c19800e8SDoug Rabson 293c19800e8SDoug Rabson memset(cred, 0, sizeof(*cred)); 294c19800e8SDoug Rabson 295c19800e8SDoug Rabson ret = krb5_unparse_name(context, incred->client, &cred->client); 296c19800e8SDoug Rabson if (ret) 297c19800e8SDoug Rabson goto fail; 298c19800e8SDoug Rabson 299c19800e8SDoug Rabson ret = krb5_unparse_name(context, incred->server, &cred->server); 300c19800e8SDoug Rabson if (ret) 301c19800e8SDoug Rabson goto fail; 302c19800e8SDoug Rabson 303c19800e8SDoug Rabson cred->keyblock.type = incred->session.keytype; 304c19800e8SDoug Rabson cred->keyblock.length = incred->session.keyvalue.length; 305c19800e8SDoug Rabson cred->keyblock.data = incred->session.keyvalue.data; 306c19800e8SDoug Rabson 307c19800e8SDoug Rabson cred->authtime = incred->times.authtime; 308c19800e8SDoug Rabson cred->starttime = incred->times.starttime; 309c19800e8SDoug Rabson cred->endtime = incred->times.endtime; 310c19800e8SDoug Rabson cred->renew_till = incred->times.renew_till; 311c19800e8SDoug Rabson 312c19800e8SDoug Rabson cred->ticket.length = incred->ticket.length; 313c19800e8SDoug Rabson cred->ticket.data = incred->ticket.data; 314c19800e8SDoug Rabson 315c19800e8SDoug Rabson cred->second_ticket.length = incred->second_ticket.length; 316c19800e8SDoug Rabson cred->second_ticket.data = incred->second_ticket.data; 317c19800e8SDoug Rabson 318c19800e8SDoug Rabson /* XXX this one should also be filled in */ 319c19800e8SDoug Rabson cred->authdata = NULL; 320c19800e8SDoug Rabson 321c19800e8SDoug Rabson cred->addresses = calloc(incred->addresses.len + 1, 322c19800e8SDoug Rabson sizeof(cred->addresses[0])); 323c19800e8SDoug Rabson if (cred->addresses == NULL) { 324c19800e8SDoug Rabson 325c19800e8SDoug Rabson ret = ENOMEM; 326c19800e8SDoug Rabson goto fail; 327c19800e8SDoug Rabson } 328c19800e8SDoug Rabson 329c19800e8SDoug Rabson for (i = 0; i < incred->addresses.len; i++) { 330c19800e8SDoug Rabson cc_data *addr; 331c19800e8SDoug Rabson addr = malloc(sizeof(*addr)); 332c19800e8SDoug Rabson if (addr == NULL) { 333c19800e8SDoug Rabson ret = ENOMEM; 334c19800e8SDoug Rabson goto fail; 335c19800e8SDoug Rabson } 336c19800e8SDoug Rabson addr->type = incred->addresses.val[i].addr_type; 337c19800e8SDoug Rabson addr->length = incred->addresses.val[i].address.length; 338c19800e8SDoug Rabson addr->data = malloc(addr->length); 339c19800e8SDoug Rabson if (addr->data == NULL) { 340c19800e8SDoug Rabson ret = ENOMEM; 341c19800e8SDoug Rabson goto fail; 342c19800e8SDoug Rabson } 343c19800e8SDoug Rabson memcpy(addr->data, incred->addresses.val[i].address.data, 344c19800e8SDoug Rabson addr->length); 345c19800e8SDoug Rabson cred->addresses[i] = addr; 346c19800e8SDoug Rabson } 347c19800e8SDoug Rabson cred->addresses[i] = NULL; 348c19800e8SDoug Rabson 349c19800e8SDoug Rabson cred->ticket_flags = 0; 350c19800e8SDoug Rabson if (incred->flags.b.forwardable) 351c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDABLE; 352c19800e8SDoug Rabson if (incred->flags.b.forwarded) 353c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDED; 354c19800e8SDoug Rabson if (incred->flags.b.proxiable) 355c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXIABLE; 356c19800e8SDoug Rabson if (incred->flags.b.proxy) 357c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXY; 358c19800e8SDoug Rabson if (incred->flags.b.may_postdate) 359c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE; 360c19800e8SDoug Rabson if (incred->flags.b.postdated) 361c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_POSTDATED; 362c19800e8SDoug Rabson if (incred->flags.b.invalid) 363c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INVALID; 364c19800e8SDoug Rabson if (incred->flags.b.renewable) 365c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_RENEWABLE; 366c19800e8SDoug Rabson if (incred->flags.b.initial) 367c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INITIAL; 368c19800e8SDoug Rabson if (incred->flags.b.pre_authent) 369c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PRE_AUTH; 370c19800e8SDoug Rabson if (incred->flags.b.hw_authent) 371c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_HW_AUTH; 372c19800e8SDoug Rabson if (incred->flags.b.transited_policy_checked) 373c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED; 374c19800e8SDoug Rabson if (incred->flags.b.ok_as_delegate) 375c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE; 376c19800e8SDoug Rabson if (incred->flags.b.anonymous) 377c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_ANONYMOUS; 378c19800e8SDoug Rabson 379c19800e8SDoug Rabson return 0; 380c19800e8SDoug Rabson 381c19800e8SDoug Rabson fail: 382c19800e8SDoug Rabson free_ccred(cred); 383c19800e8SDoug Rabson 384c19800e8SDoug Rabson krb5_clear_error_string(context); 385c19800e8SDoug Rabson return ret; 386c19800e8SDoug Rabson } 387c19800e8SDoug Rabson 388c19800e8SDoug Rabson static char * 389c19800e8SDoug Rabson get_cc_name(cc_ccache_t cache) 390c19800e8SDoug Rabson { 391c19800e8SDoug Rabson cc_string_t name; 392c19800e8SDoug Rabson cc_int32 error; 393c19800e8SDoug Rabson char *str; 394c19800e8SDoug Rabson 395c19800e8SDoug Rabson error = (*cache->func->get_name)(cache, &name); 396c19800e8SDoug Rabson if (error) 397c19800e8SDoug Rabson return NULL; 398c19800e8SDoug Rabson 399c19800e8SDoug Rabson str = strdup(name->data); 400c19800e8SDoug Rabson (*name->func->release)(name); 401c19800e8SDoug Rabson return str; 402c19800e8SDoug Rabson } 403c19800e8SDoug Rabson 404c19800e8SDoug Rabson 405c19800e8SDoug Rabson static const char* 406c19800e8SDoug Rabson acc_get_name(krb5_context context, 407c19800e8SDoug Rabson krb5_ccache id) 408c19800e8SDoug Rabson { 409c19800e8SDoug Rabson krb5_acc *a = ACACHE(id); 410c19800e8SDoug Rabson static char n[255]; 411c19800e8SDoug Rabson char *name; 412c19800e8SDoug Rabson 413c19800e8SDoug Rabson name = get_cc_name(a->ccache); 414c19800e8SDoug Rabson if (name == NULL) { 415c19800e8SDoug Rabson krb5_set_error_string(context, "malloc: out of memory"); 416c19800e8SDoug Rabson return NULL; 417c19800e8SDoug Rabson } 418c19800e8SDoug Rabson strlcpy(n, name, sizeof(n)); 419c19800e8SDoug Rabson free(name); 420c19800e8SDoug Rabson return n; 421c19800e8SDoug Rabson } 422c19800e8SDoug Rabson 423c19800e8SDoug Rabson static krb5_error_code 424c19800e8SDoug Rabson acc_alloc(krb5_context context, krb5_ccache *id) 425c19800e8SDoug Rabson { 426c19800e8SDoug Rabson krb5_error_code ret; 427c19800e8SDoug Rabson cc_int32 error; 428c19800e8SDoug Rabson krb5_acc *a; 429c19800e8SDoug Rabson 430c19800e8SDoug Rabson ret = init_ccapi(context); 431c19800e8SDoug Rabson if (ret) 432c19800e8SDoug Rabson return ret; 433c19800e8SDoug Rabson 434c19800e8SDoug Rabson ret = krb5_data_alloc(&(*id)->data, sizeof(*a)); 435c19800e8SDoug Rabson if (ret) { 436c19800e8SDoug Rabson krb5_clear_error_string(context); 437c19800e8SDoug Rabson return ret; 438c19800e8SDoug Rabson } 439c19800e8SDoug Rabson 440c19800e8SDoug Rabson a = ACACHE(*id); 441c19800e8SDoug Rabson 442c19800e8SDoug Rabson error = (*init_func)(&a->context, ccapi_version_3, NULL, NULL); 443c19800e8SDoug Rabson if (error) { 444c19800e8SDoug Rabson krb5_data_free(&(*id)->data); 445c19800e8SDoug Rabson return translate_cc_error(context, error); 446c19800e8SDoug Rabson } 447c19800e8SDoug Rabson 448c19800e8SDoug Rabson a->cache_name = NULL; 449c19800e8SDoug Rabson 450c19800e8SDoug Rabson return 0; 451c19800e8SDoug Rabson } 452c19800e8SDoug Rabson 453c19800e8SDoug Rabson static krb5_error_code 454c19800e8SDoug Rabson acc_resolve(krb5_context context, krb5_ccache *id, const char *res) 455c19800e8SDoug Rabson { 456c19800e8SDoug Rabson krb5_error_code ret; 457c19800e8SDoug Rabson cc_int32 error; 458c19800e8SDoug Rabson krb5_acc *a; 459c19800e8SDoug Rabson 460c19800e8SDoug Rabson ret = acc_alloc(context, id); 461c19800e8SDoug Rabson if (ret) 462c19800e8SDoug Rabson return ret; 463c19800e8SDoug Rabson 464c19800e8SDoug Rabson a = ACACHE(*id); 465c19800e8SDoug Rabson 466c19800e8SDoug Rabson error = (*a->context->func->open_ccache)(a->context, res, 467c19800e8SDoug Rabson &a->ccache); 468c19800e8SDoug Rabson if (error == 0) { 469c19800e8SDoug Rabson a->cache_name = get_cc_name(a->ccache); 470c19800e8SDoug Rabson if (a->cache_name == NULL) { 471c19800e8SDoug Rabson acc_close(context, *id); 472c19800e8SDoug Rabson *id = NULL; 473c19800e8SDoug Rabson krb5_set_error_string(context, "malloc: out of memory"); 474c19800e8SDoug Rabson return ENOMEM; 475c19800e8SDoug Rabson } 476c19800e8SDoug Rabson } else if (error == ccErrCCacheNotFound) { 477c19800e8SDoug Rabson a->ccache = NULL; 478c19800e8SDoug Rabson a->cache_name = NULL; 479c19800e8SDoug Rabson error = 0; 480c19800e8SDoug Rabson } else { 481c19800e8SDoug Rabson *id = NULL; 482c19800e8SDoug Rabson return translate_cc_error(context, error); 483c19800e8SDoug Rabson } 484c19800e8SDoug Rabson 485c19800e8SDoug Rabson return 0; 486c19800e8SDoug Rabson } 487c19800e8SDoug Rabson 488c19800e8SDoug Rabson static krb5_error_code 489c19800e8SDoug Rabson acc_gen_new(krb5_context context, krb5_ccache *id) 490c19800e8SDoug Rabson { 491c19800e8SDoug Rabson krb5_error_code ret; 492c19800e8SDoug Rabson krb5_acc *a; 493c19800e8SDoug Rabson 494c19800e8SDoug Rabson ret = acc_alloc(context, id); 495c19800e8SDoug Rabson if (ret) 496c19800e8SDoug Rabson return ret; 497c19800e8SDoug Rabson 498c19800e8SDoug Rabson a = ACACHE(*id); 499c19800e8SDoug Rabson 500c19800e8SDoug Rabson a->ccache = NULL; 501c19800e8SDoug Rabson a->cache_name = NULL; 502c19800e8SDoug Rabson 503c19800e8SDoug Rabson return 0; 504c19800e8SDoug Rabson } 505c19800e8SDoug Rabson 506c19800e8SDoug Rabson static krb5_error_code 507c19800e8SDoug Rabson acc_initialize(krb5_context context, 508c19800e8SDoug Rabson krb5_ccache id, 509c19800e8SDoug Rabson krb5_principal primary_principal) 510c19800e8SDoug Rabson { 511c19800e8SDoug Rabson krb5_acc *a = ACACHE(id); 512c19800e8SDoug Rabson krb5_error_code ret; 513c19800e8SDoug Rabson int32_t error; 514c19800e8SDoug Rabson char *name; 515c19800e8SDoug Rabson 516c19800e8SDoug Rabson ret = krb5_unparse_name(context, primary_principal, &name); 517c19800e8SDoug Rabson if (ret) 518c19800e8SDoug Rabson return ret; 519c19800e8SDoug Rabson 520c19800e8SDoug Rabson error = (*a->context->func->create_new_ccache)(a->context, 521c19800e8SDoug Rabson cc_credentials_v5, 522c19800e8SDoug Rabson name, 523c19800e8SDoug Rabson &a->ccache); 524c19800e8SDoug Rabson free(name); 525c19800e8SDoug Rabson 526c19800e8SDoug Rabson return translate_cc_error(context, error); 527c19800e8SDoug Rabson } 528c19800e8SDoug Rabson 529c19800e8SDoug Rabson static krb5_error_code 530c19800e8SDoug Rabson acc_close(krb5_context context, 531c19800e8SDoug Rabson krb5_ccache id) 532c19800e8SDoug Rabson { 533c19800e8SDoug Rabson krb5_acc *a = ACACHE(id); 534c19800e8SDoug Rabson 535c19800e8SDoug Rabson if (a->ccache) { 536c19800e8SDoug Rabson (*a->ccache->func->release)(a->ccache); 537c19800e8SDoug Rabson a->ccache = NULL; 538c19800e8SDoug Rabson } 539c19800e8SDoug Rabson if (a->cache_name) { 540c19800e8SDoug Rabson free(a->cache_name); 541c19800e8SDoug Rabson a->cache_name = NULL; 542c19800e8SDoug Rabson } 543c19800e8SDoug Rabson (*a->context->func->release)(a->context); 544c19800e8SDoug Rabson a->context = NULL; 545c19800e8SDoug Rabson krb5_data_free(&id->data); 546c19800e8SDoug Rabson return 0; 547c19800e8SDoug Rabson } 548c19800e8SDoug Rabson 549c19800e8SDoug Rabson static krb5_error_code 550c19800e8SDoug Rabson acc_destroy(krb5_context context, 551c19800e8SDoug Rabson krb5_ccache id) 552c19800e8SDoug Rabson { 553c19800e8SDoug Rabson krb5_acc *a = ACACHE(id); 554c19800e8SDoug Rabson cc_int32 error = 0; 555c19800e8SDoug Rabson 556c19800e8SDoug Rabson if (a->ccache) { 557c19800e8SDoug Rabson error = (*a->ccache->func->destroy)(a->ccache); 558c19800e8SDoug Rabson a->ccache = NULL; 559c19800e8SDoug Rabson } 560c19800e8SDoug Rabson if (a->context) { 561c19800e8SDoug Rabson error = (a->context->func->release)(a->context); 562c19800e8SDoug Rabson a->context = NULL; 563c19800e8SDoug Rabson } 564c19800e8SDoug Rabson return translate_cc_error(context, error); 565c19800e8SDoug Rabson } 566c19800e8SDoug Rabson 567c19800e8SDoug Rabson static krb5_error_code 568c19800e8SDoug Rabson acc_store_cred(krb5_context context, 569c19800e8SDoug Rabson krb5_ccache id, 570c19800e8SDoug Rabson krb5_creds *creds) 571c19800e8SDoug Rabson { 572c19800e8SDoug Rabson krb5_acc *a = ACACHE(id); 573c19800e8SDoug Rabson cc_credentials_union cred; 574c19800e8SDoug Rabson cc_credentials_v5_t v5cred; 575c19800e8SDoug Rabson krb5_error_code ret; 576c19800e8SDoug Rabson cc_int32 error; 577c19800e8SDoug Rabson 578c19800e8SDoug Rabson if (a->ccache == NULL) { 579c19800e8SDoug Rabson krb5_set_error_string(context, "No API credential found"); 580c19800e8SDoug Rabson return KRB5_CC_NOTFOUND; 581c19800e8SDoug Rabson } 582c19800e8SDoug Rabson 583c19800e8SDoug Rabson cred.version = cc_credentials_v5; 584c19800e8SDoug Rabson cred.credentials.credentials_v5 = &v5cred; 585c19800e8SDoug Rabson 586c19800e8SDoug Rabson ret = make_ccred_from_cred(context, 587c19800e8SDoug Rabson creds, 588c19800e8SDoug Rabson &v5cred); 589c19800e8SDoug Rabson if (ret) 590c19800e8SDoug Rabson return ret; 591c19800e8SDoug Rabson 592c19800e8SDoug Rabson error = (*a->ccache->func->store_credentials)(a->ccache, &cred); 593c19800e8SDoug Rabson if (error) 594c19800e8SDoug Rabson ret = translate_cc_error(context, error); 595c19800e8SDoug Rabson 596c19800e8SDoug Rabson free_ccred(&v5cred); 597c19800e8SDoug Rabson 598c19800e8SDoug Rabson return ret; 599c19800e8SDoug Rabson } 600c19800e8SDoug Rabson 601c19800e8SDoug Rabson static krb5_error_code 602c19800e8SDoug Rabson acc_get_principal(krb5_context context, 603c19800e8SDoug Rabson krb5_ccache id, 604c19800e8SDoug Rabson krb5_principal *principal) 605c19800e8SDoug Rabson { 606c19800e8SDoug Rabson krb5_acc *a = ACACHE(id); 607c19800e8SDoug Rabson krb5_error_code ret; 608c19800e8SDoug Rabson int32_t error; 609c19800e8SDoug Rabson cc_string_t name; 610c19800e8SDoug Rabson 611c19800e8SDoug Rabson if (a->ccache == NULL) { 612c19800e8SDoug Rabson krb5_set_error_string(context, "No API credential found"); 613c19800e8SDoug Rabson return KRB5_CC_NOTFOUND; 614c19800e8SDoug Rabson } 615c19800e8SDoug Rabson 616c19800e8SDoug Rabson error = (*a->ccache->func->get_principal)(a->ccache, 617c19800e8SDoug Rabson cc_credentials_v5, 618c19800e8SDoug Rabson &name); 619c19800e8SDoug Rabson if (error) 620c19800e8SDoug Rabson return translate_cc_error(context, error); 621c19800e8SDoug Rabson 622c19800e8SDoug Rabson ret = krb5_parse_name(context, name->data, principal); 623c19800e8SDoug Rabson 624c19800e8SDoug Rabson (*name->func->release)(name); 625c19800e8SDoug Rabson return ret; 626c19800e8SDoug Rabson } 627c19800e8SDoug Rabson 628c19800e8SDoug Rabson static krb5_error_code 629c19800e8SDoug Rabson acc_get_first (krb5_context context, 630c19800e8SDoug Rabson krb5_ccache id, 631c19800e8SDoug Rabson krb5_cc_cursor *cursor) 632c19800e8SDoug Rabson { 633c19800e8SDoug Rabson cc_credentials_iterator_t iter; 634c19800e8SDoug Rabson krb5_acc *a = ACACHE(id); 635c19800e8SDoug Rabson int32_t error; 636c19800e8SDoug Rabson 637c19800e8SDoug Rabson if (a->ccache == NULL) { 638c19800e8SDoug Rabson krb5_set_error_string(context, "No API credential found"); 639c19800e8SDoug Rabson return KRB5_CC_NOTFOUND; 640c19800e8SDoug Rabson } 641c19800e8SDoug Rabson 642c19800e8SDoug Rabson error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); 643c19800e8SDoug Rabson if (error) { 644c19800e8SDoug Rabson krb5_clear_error_string(context); 645c19800e8SDoug Rabson return ENOENT; 646c19800e8SDoug Rabson } 647c19800e8SDoug Rabson *cursor = iter; 648c19800e8SDoug Rabson return 0; 649c19800e8SDoug Rabson } 650c19800e8SDoug Rabson 651c19800e8SDoug Rabson 652c19800e8SDoug Rabson static krb5_error_code 653c19800e8SDoug Rabson acc_get_next (krb5_context context, 654c19800e8SDoug Rabson krb5_ccache id, 655c19800e8SDoug Rabson krb5_cc_cursor *cursor, 656c19800e8SDoug Rabson krb5_creds *creds) 657c19800e8SDoug Rabson { 658c19800e8SDoug Rabson cc_credentials_iterator_t iter = *cursor; 659c19800e8SDoug Rabson cc_credentials_t cred; 660c19800e8SDoug Rabson krb5_error_code ret; 661c19800e8SDoug Rabson int32_t error; 662c19800e8SDoug Rabson 663c19800e8SDoug Rabson while (1) { 664c19800e8SDoug Rabson error = (*iter->func->next)(iter, &cred); 665c19800e8SDoug Rabson if (error) 666c19800e8SDoug Rabson return translate_cc_error(context, error); 667c19800e8SDoug Rabson if (cred->data->version == cc_credentials_v5) 668c19800e8SDoug Rabson break; 669c19800e8SDoug Rabson (*cred->func->release)(cred); 670c19800e8SDoug Rabson } 671c19800e8SDoug Rabson 672c19800e8SDoug Rabson ret = make_cred_from_ccred(context, 673c19800e8SDoug Rabson cred->data->credentials.credentials_v5, 674c19800e8SDoug Rabson creds); 675c19800e8SDoug Rabson (*cred->func->release)(cred); 676c19800e8SDoug Rabson return ret; 677c19800e8SDoug Rabson } 678c19800e8SDoug Rabson 679c19800e8SDoug Rabson static krb5_error_code 680c19800e8SDoug Rabson acc_end_get (krb5_context context, 681c19800e8SDoug Rabson krb5_ccache id, 682c19800e8SDoug Rabson krb5_cc_cursor *cursor) 683c19800e8SDoug Rabson { 684c19800e8SDoug Rabson cc_credentials_iterator_t iter = *cursor; 685c19800e8SDoug Rabson (*iter->func->release)(iter); 686c19800e8SDoug Rabson return 0; 687c19800e8SDoug Rabson } 688c19800e8SDoug Rabson 689c19800e8SDoug Rabson static krb5_error_code 690c19800e8SDoug Rabson acc_remove_cred(krb5_context context, 691c19800e8SDoug Rabson krb5_ccache id, 692c19800e8SDoug Rabson krb5_flags which, 693c19800e8SDoug Rabson krb5_creds *cred) 694c19800e8SDoug Rabson { 695c19800e8SDoug Rabson cc_credentials_iterator_t iter; 696c19800e8SDoug Rabson krb5_acc *a = ACACHE(id); 697c19800e8SDoug Rabson cc_credentials_t ccred; 698c19800e8SDoug Rabson krb5_error_code ret; 699c19800e8SDoug Rabson cc_int32 error; 700c19800e8SDoug Rabson char *client, *server; 701c19800e8SDoug Rabson 702c19800e8SDoug Rabson if (a->ccache == NULL) { 703c19800e8SDoug Rabson krb5_set_error_string(context, "No API credential found"); 704c19800e8SDoug Rabson return KRB5_CC_NOTFOUND; 705c19800e8SDoug Rabson } 706c19800e8SDoug Rabson 707c19800e8SDoug Rabson if (cred->client) { 708c19800e8SDoug Rabson ret = krb5_unparse_name(context, cred->client, &client); 709c19800e8SDoug Rabson if (ret) 710c19800e8SDoug Rabson return ret; 711c19800e8SDoug Rabson } else 712c19800e8SDoug Rabson client = NULL; 713c19800e8SDoug Rabson 714c19800e8SDoug Rabson ret = krb5_unparse_name(context, cred->server, &server); 715c19800e8SDoug Rabson if (ret) { 716c19800e8SDoug Rabson free(client); 717c19800e8SDoug Rabson return ret; 718c19800e8SDoug Rabson } 719c19800e8SDoug Rabson 720c19800e8SDoug Rabson error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); 721c19800e8SDoug Rabson if (error) { 722c19800e8SDoug Rabson free(server); 723c19800e8SDoug Rabson free(client); 724c19800e8SDoug Rabson return translate_cc_error(context, error); 725c19800e8SDoug Rabson } 726c19800e8SDoug Rabson 727c19800e8SDoug Rabson ret = KRB5_CC_NOTFOUND; 728c19800e8SDoug Rabson while (1) { 729c19800e8SDoug Rabson cc_credentials_v5_t *v5cred; 730c19800e8SDoug Rabson 731c19800e8SDoug Rabson error = (*iter->func->next)(iter, &ccred); 732c19800e8SDoug Rabson if (error) 733c19800e8SDoug Rabson break; 734c19800e8SDoug Rabson 735c19800e8SDoug Rabson if (ccred->data->version != cc_credentials_v5) 736c19800e8SDoug Rabson goto next; 737c19800e8SDoug Rabson 738c19800e8SDoug Rabson v5cred = ccred->data->credentials.credentials_v5; 739c19800e8SDoug Rabson 740c19800e8SDoug Rabson if (client && strcmp(v5cred->client, client) != 0) 741c19800e8SDoug Rabson goto next; 742c19800e8SDoug Rabson 743c19800e8SDoug Rabson if (strcmp(v5cred->server, server) != 0) 744c19800e8SDoug Rabson goto next; 745c19800e8SDoug Rabson 746c19800e8SDoug Rabson (*a->ccache->func->remove_credentials)(a->ccache, ccred); 747c19800e8SDoug Rabson ret = 0; 748c19800e8SDoug Rabson next: 749c19800e8SDoug Rabson (*ccred->func->release)(ccred); 750c19800e8SDoug Rabson } 751c19800e8SDoug Rabson 752c19800e8SDoug Rabson (*iter->func->release)(iter); 753c19800e8SDoug Rabson 754c19800e8SDoug Rabson if (ret) 755c19800e8SDoug Rabson krb5_set_error_string(context, "Can't find credential %s in cache", 756c19800e8SDoug Rabson server); 757c19800e8SDoug Rabson free(server); 758c19800e8SDoug Rabson free(client); 759c19800e8SDoug Rabson 760c19800e8SDoug Rabson return ret; 761c19800e8SDoug Rabson } 762c19800e8SDoug Rabson 763c19800e8SDoug Rabson static krb5_error_code 764c19800e8SDoug Rabson acc_set_flags(krb5_context context, 765c19800e8SDoug Rabson krb5_ccache id, 766c19800e8SDoug Rabson krb5_flags flags) 767c19800e8SDoug Rabson { 768c19800e8SDoug Rabson return 0; 769c19800e8SDoug Rabson } 770c19800e8SDoug Rabson 771c19800e8SDoug Rabson static krb5_error_code 772c19800e8SDoug Rabson acc_get_version(krb5_context context, 773c19800e8SDoug Rabson krb5_ccache id) 774c19800e8SDoug Rabson { 775c19800e8SDoug Rabson return 0; 776c19800e8SDoug Rabson } 777c19800e8SDoug Rabson 778c19800e8SDoug Rabson struct cache_iter { 779c19800e8SDoug Rabson cc_context_t context; 780c19800e8SDoug Rabson cc_ccache_iterator_t iter; 781c19800e8SDoug Rabson }; 782c19800e8SDoug Rabson 783c19800e8SDoug Rabson static krb5_error_code 784c19800e8SDoug Rabson acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) 785c19800e8SDoug Rabson { 786c19800e8SDoug Rabson struct cache_iter *iter; 787c19800e8SDoug Rabson krb5_error_code ret; 788c19800e8SDoug Rabson cc_int32 error; 789c19800e8SDoug Rabson 790c19800e8SDoug Rabson ret = init_ccapi(context); 791c19800e8SDoug Rabson if (ret) 792c19800e8SDoug Rabson return ret; 793c19800e8SDoug Rabson 794c19800e8SDoug Rabson iter = calloc(1, sizeof(*iter)); 795c19800e8SDoug Rabson if (iter == NULL) { 796c19800e8SDoug Rabson krb5_set_error_string(context, "malloc - out of memory"); 797c19800e8SDoug Rabson return ENOMEM; 798c19800e8SDoug Rabson } 799c19800e8SDoug Rabson 800c19800e8SDoug Rabson error = (*init_func)(&iter->context, ccapi_version_3, NULL, NULL); 801c19800e8SDoug Rabson if (error) { 802c19800e8SDoug Rabson free(iter); 803c19800e8SDoug Rabson return translate_cc_error(context, error); 804c19800e8SDoug Rabson } 805c19800e8SDoug Rabson 806c19800e8SDoug Rabson error = (*iter->context->func->new_ccache_iterator)(iter->context, 807c19800e8SDoug Rabson &iter->iter); 808c19800e8SDoug Rabson if (error) { 809c19800e8SDoug Rabson free(iter); 810c19800e8SDoug Rabson krb5_clear_error_string(context); 811c19800e8SDoug Rabson return ENOENT; 812c19800e8SDoug Rabson } 813c19800e8SDoug Rabson *cursor = iter; 814c19800e8SDoug Rabson return 0; 815c19800e8SDoug Rabson } 816c19800e8SDoug Rabson 817c19800e8SDoug Rabson static krb5_error_code 818c19800e8SDoug Rabson acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) 819c19800e8SDoug Rabson { 820c19800e8SDoug Rabson struct cache_iter *iter = cursor; 821c19800e8SDoug Rabson cc_ccache_t cache; 822c19800e8SDoug Rabson krb5_acc *a; 823c19800e8SDoug Rabson krb5_error_code ret; 824c19800e8SDoug Rabson int32_t error; 825c19800e8SDoug Rabson 826c19800e8SDoug Rabson error = (*iter->iter->func->next)(iter->iter, &cache); 827c19800e8SDoug Rabson if (error) 828c19800e8SDoug Rabson return translate_cc_error(context, error); 829c19800e8SDoug Rabson 830c19800e8SDoug Rabson ret = _krb5_cc_allocate(context, &krb5_acc_ops, id); 831c19800e8SDoug Rabson if (ret) { 832c19800e8SDoug Rabson (*cache->func->release)(cache); 833c19800e8SDoug Rabson return ret; 834c19800e8SDoug Rabson } 835c19800e8SDoug Rabson 836c19800e8SDoug Rabson ret = acc_alloc(context, id); 837c19800e8SDoug Rabson if (ret) { 838c19800e8SDoug Rabson (*cache->func->release)(cache); 839c19800e8SDoug Rabson free(*id); 840c19800e8SDoug Rabson return ret; 841c19800e8SDoug Rabson } 842c19800e8SDoug Rabson 843c19800e8SDoug Rabson a = ACACHE(*id); 844c19800e8SDoug Rabson a->ccache = cache; 845c19800e8SDoug Rabson 846c19800e8SDoug Rabson a->cache_name = get_cc_name(a->ccache); 847c19800e8SDoug Rabson if (a->cache_name == NULL) { 848c19800e8SDoug Rabson acc_close(context, *id); 849c19800e8SDoug Rabson *id = NULL; 850c19800e8SDoug Rabson krb5_set_error_string(context, "malloc: out of memory"); 851c19800e8SDoug Rabson return ENOMEM; 852c19800e8SDoug Rabson } 853c19800e8SDoug Rabson return 0; 854c19800e8SDoug Rabson } 855c19800e8SDoug Rabson 856c19800e8SDoug Rabson static krb5_error_code 857c19800e8SDoug Rabson acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) 858c19800e8SDoug Rabson { 859c19800e8SDoug Rabson struct cache_iter *iter = cursor; 860c19800e8SDoug Rabson 861c19800e8SDoug Rabson (*iter->iter->func->release)(iter->iter); 862c19800e8SDoug Rabson iter->iter = NULL; 863c19800e8SDoug Rabson (*iter->context->func->release)(iter->context); 864c19800e8SDoug Rabson iter->context = NULL; 865c19800e8SDoug Rabson free(iter); 866c19800e8SDoug Rabson return 0; 867c19800e8SDoug Rabson } 868c19800e8SDoug Rabson 869c19800e8SDoug Rabson static krb5_error_code 870c19800e8SDoug Rabson acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) 871c19800e8SDoug Rabson { 872c19800e8SDoug Rabson krb5_acc *afrom = ACACHE(from); 873c19800e8SDoug Rabson krb5_acc *ato = ACACHE(to); 874c19800e8SDoug Rabson int32_t error; 875c19800e8SDoug Rabson 876c19800e8SDoug Rabson if (ato->ccache == NULL) { 877c19800e8SDoug Rabson cc_string_t name; 878c19800e8SDoug Rabson 879c19800e8SDoug Rabson error = (*afrom->ccache->func->get_principal)(afrom->ccache, 880c19800e8SDoug Rabson cc_credentials_v5, 881c19800e8SDoug Rabson &name); 882c19800e8SDoug Rabson if (error) 883c19800e8SDoug Rabson return translate_cc_error(context, error); 884c19800e8SDoug Rabson 885c19800e8SDoug Rabson error = (*ato->context->func->create_new_ccache)(ato->context, 886c19800e8SDoug Rabson cc_credentials_v5, 887c19800e8SDoug Rabson name->data, 888c19800e8SDoug Rabson &ato->ccache); 889c19800e8SDoug Rabson (*name->func->release)(name); 890c19800e8SDoug Rabson if (error) 891c19800e8SDoug Rabson return translate_cc_error(context, error); 892c19800e8SDoug Rabson } 893c19800e8SDoug Rabson 894c19800e8SDoug Rabson 895c19800e8SDoug Rabson error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache); 896c19800e8SDoug Rabson return translate_cc_error(context, error); 897c19800e8SDoug Rabson } 898c19800e8SDoug Rabson 899c19800e8SDoug Rabson static krb5_error_code 900c19800e8SDoug Rabson acc_default_name(krb5_context context, char **str) 901c19800e8SDoug Rabson { 902c19800e8SDoug Rabson krb5_error_code ret; 903c19800e8SDoug Rabson cc_context_t cc; 904c19800e8SDoug Rabson cc_string_t name; 905c19800e8SDoug Rabson int32_t error; 906c19800e8SDoug Rabson 907c19800e8SDoug Rabson ret = init_ccapi(context); 908c19800e8SDoug Rabson if (ret) 909c19800e8SDoug Rabson return ret; 910c19800e8SDoug Rabson 911c19800e8SDoug Rabson error = (*init_func)(&cc, ccapi_version_3, NULL, NULL); 912c19800e8SDoug Rabson if (error) 913c19800e8SDoug Rabson return translate_cc_error(context, error); 914c19800e8SDoug Rabson 915c19800e8SDoug Rabson error = (*cc->func->get_default_ccache_name)(cc, &name); 916c19800e8SDoug Rabson if (error) { 917c19800e8SDoug Rabson (*cc->func->release)(cc); 918c19800e8SDoug Rabson return translate_cc_error(context, error); 919c19800e8SDoug Rabson } 920c19800e8SDoug Rabson 921c19800e8SDoug Rabson asprintf(str, "API:%s", name->data); 922c19800e8SDoug Rabson (*name->func->release)(name); 923c19800e8SDoug Rabson (*cc->func->release)(cc); 924c19800e8SDoug Rabson 925c19800e8SDoug Rabson if (*str == NULL) { 926c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 927c19800e8SDoug Rabson return ENOMEM; 928c19800e8SDoug Rabson } 929c19800e8SDoug Rabson return 0; 930c19800e8SDoug Rabson } 931c19800e8SDoug Rabson 932c19800e8SDoug Rabson 933c19800e8SDoug Rabson /** 934c19800e8SDoug Rabson * Variable containing the API based credential cache implemention. 935c19800e8SDoug Rabson * 936c19800e8SDoug Rabson * @ingroup krb5_ccache 937c19800e8SDoug Rabson */ 938c19800e8SDoug Rabson 939c19800e8SDoug Rabson const krb5_cc_ops krb5_acc_ops = { 940c19800e8SDoug Rabson "API", 941c19800e8SDoug Rabson acc_get_name, 942c19800e8SDoug Rabson acc_resolve, 943c19800e8SDoug Rabson acc_gen_new, 944c19800e8SDoug Rabson acc_initialize, 945c19800e8SDoug Rabson acc_destroy, 946c19800e8SDoug Rabson acc_close, 947c19800e8SDoug Rabson acc_store_cred, 948c19800e8SDoug Rabson NULL, /* acc_retrieve */ 949c19800e8SDoug Rabson acc_get_principal, 950c19800e8SDoug Rabson acc_get_first, 951c19800e8SDoug Rabson acc_get_next, 952c19800e8SDoug Rabson acc_end_get, 953c19800e8SDoug Rabson acc_remove_cred, 954c19800e8SDoug Rabson acc_set_flags, 955c19800e8SDoug Rabson acc_get_version, 956c19800e8SDoug Rabson acc_get_cache_first, 957c19800e8SDoug Rabson acc_get_cache_next, 958c19800e8SDoug Rabson acc_end_cache_get, 959c19800e8SDoug Rabson acc_move, 960c19800e8SDoug Rabson acc_default_name 961c19800e8SDoug Rabson }; 962