📄 acache.c
字号:
/* * Copyright (c) 2004 - 2007 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "krb5_locl.h"#include <krb5_ccapi.h>#ifdef HAVE_DLFCN_H#include <dlfcn.h>#endifRCSID("$Id: acache.c 22669 2008-03-09 23:39:25Z lha $");/* XXX should we fetch these for each open ? */static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;static cc_initialize_func init_func;#ifdef HAVE_DLOPENstatic void *cc_handle; #endiftypedef struct krb5_acc { char *cache_name; cc_context_t context; cc_ccache_t ccache;} krb5_acc;static krb5_error_code acc_close(krb5_context, krb5_ccache);#define ACACHE(X) ((krb5_acc *)(X)->data.data)static const struct { cc_int32 error; krb5_error_code ret;} cc_errors[] = { { ccErrBadName, KRB5_CC_BADNAME }, { ccErrCredentialsNotFound, KRB5_CC_NOTFOUND }, { ccErrCCacheNotFound, KRB5_FCC_NOFILE }, { ccErrContextNotFound, KRB5_CC_NOTFOUND }, { ccIteratorEnd, KRB5_CC_END }, { ccErrNoMem, KRB5_CC_NOMEM }, { ccErrServerUnavailable, KRB5_CC_NOSUPP }, { ccNoError, 0 }};static krb5_error_codetranslate_cc_error(krb5_context context, cc_int32 error){ int i; krb5_clear_error_string(context); for(i = 0; i < sizeof(cc_errors)/sizeof(cc_errors[0]); i++) if (cc_errors[i].error == error) return cc_errors[i].ret; return KRB5_FCC_INTERNAL;}static krb5_error_codeinit_ccapi(krb5_context context){ const char *lib; HEIMDAL_MUTEX_lock(&acc_mutex); if (init_func) { HEIMDAL_MUTEX_unlock(&acc_mutex); krb5_clear_error_string(context); return 0; } lib = krb5_config_get_string(context, NULL, "libdefaults", "ccapi_library", NULL); if (lib == NULL) {#ifdef __APPLE__ lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos";#else lib = "/usr/lib/libkrb5_cc.so";#endif }#ifdef HAVE_DLOPEN#ifndef RTLD_LAZY#define RTLD_LAZY 0#endif cc_handle = dlopen(lib, RTLD_LAZY); if (cc_handle == NULL) { HEIMDAL_MUTEX_unlock(&acc_mutex); krb5_set_error_string(context, "Failed to load %s", lib); return KRB5_CC_NOSUPP; } init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize"); HEIMDAL_MUTEX_unlock(&acc_mutex); if (init_func == NULL) { krb5_set_error_string(context, "Failed to find cc_initialize" "in %s: %s", lib, dlerror()); dlclose(cc_handle); return KRB5_CC_NOSUPP; } return 0;#else HEIMDAL_MUTEX_unlock(&acc_mutex); krb5_set_error_string(context, "no support for shared object"); return KRB5_CC_NOSUPP;#endif} static krb5_error_codemake_cred_from_ccred(krb5_context context, const cc_credentials_v5_t *incred, krb5_creds *cred){ krb5_error_code ret; int i; memset(cred, 0, sizeof(*cred)); ret = krb5_parse_name(context, incred->client, &cred->client); if (ret) goto fail; ret = krb5_parse_name(context, incred->server, &cred->server); if (ret) goto fail; cred->session.keytype = incred->keyblock.type; cred->session.keyvalue.length = incred->keyblock.length; cred->session.keyvalue.data = malloc(incred->keyblock.length); if (cred->session.keyvalue.data == NULL) goto nomem; memcpy(cred->session.keyvalue.data, incred->keyblock.data, incred->keyblock.length); cred->times.authtime = incred->authtime; cred->times.starttime = incred->starttime; cred->times.endtime = incred->endtime; cred->times.renew_till = incred->renew_till; ret = krb5_data_copy(&cred->ticket, incred->ticket.data, incred->ticket.length); if (ret) goto nomem; ret = krb5_data_copy(&cred->second_ticket, incred->second_ticket.data, incred->second_ticket.length); if (ret) goto nomem; cred->authdata.val = NULL; cred->authdata.len = 0; cred->addresses.val = NULL; cred->addresses.len = 0; for (i = 0; incred->authdata && incred->authdata[i]; i++) ; if (i) { cred->authdata.val = calloc(i, sizeof(cred->authdata.val[0])); if (cred->authdata.val == NULL) goto nomem; cred->authdata.len = i; for (i = 0; i < cred->authdata.len; i++) { cred->authdata.val[i].ad_type = incred->authdata[i]->type; ret = krb5_data_copy(&cred->authdata.val[i].ad_data, incred->authdata[i]->data, incred->authdata[i]->length); if (ret) goto nomem; } } for (i = 0; incred->addresses && incred->addresses[i]; i++) ; if (i) { cred->addresses.val = calloc(i, sizeof(cred->addresses.val[0])); if (cred->addresses.val == NULL) goto nomem; cred->addresses.len = i; for (i = 0; i < cred->addresses.len; i++) { cred->addresses.val[i].addr_type = incred->addresses[i]->type; ret = krb5_data_copy(&cred->addresses.val[i].address, incred->addresses[i]->data, incred->addresses[i]->length); if (ret) goto nomem; } } cred->flags.i = 0; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDABLE) cred->flags.b.forwardable = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDED) cred->flags.b.forwarded = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXIABLE) cred->flags.b.proxiable = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXY) cred->flags.b.proxy = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_MAY_POSTDATE) cred->flags.b.may_postdate = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_POSTDATED) cred->flags.b.postdated = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INVALID) cred->flags.b.invalid = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_RENEWABLE) cred->flags.b.renewable = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INITIAL) cred->flags.b.initial = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PRE_AUTH) cred->flags.b.pre_authent = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_HW_AUTH) cred->flags.b.hw_authent = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED) cred->flags.b.transited_policy_checked = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE) cred->flags.b.ok_as_delegate = 1; if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_ANONYMOUS) cred->flags.b.anonymous = 1; return 0; nomem: ret = ENOMEM; krb5_set_error_string(context, "malloc - out of memory"); fail: krb5_free_cred_contents(context, cred); return ret;}static voidfree_ccred(cc_credentials_v5_t *cred){ int i; if (cred->addresses) { for (i = 0; cred->addresses[i] != 0; i++) { if (cred->addresses[i]->data) free(cred->addresses[i]->data); free(cred->addresses[i]); } free(cred->addresses); } if (cred->server) free(cred->server); if (cred->client) free(cred->client); memset(cred, 0, sizeof(*cred));}static krb5_error_codemake_ccred_from_cred(krb5_context context, const krb5_creds *incred, cc_credentials_v5_t *cred){ krb5_error_code ret; int i; memset(cred, 0, sizeof(*cred)); ret = krb5_unparse_name(context, incred->client, &cred->client); if (ret) goto fail; ret = krb5_unparse_name(context, incred->server, &cred->server); if (ret) goto fail; cred->keyblock.type = incred->session.keytype; cred->keyblock.length = incred->session.keyvalue.length; cred->keyblock.data = incred->session.keyvalue.data; cred->authtime = incred->times.authtime; cred->starttime = incred->times.starttime; cred->endtime = incred->times.endtime; cred->renew_till = incred->times.renew_till; cred->ticket.length = incred->ticket.length; cred->ticket.data = incred->ticket.data; cred->second_ticket.length = incred->second_ticket.length; cred->second_ticket.data = incred->second_ticket.data; /* XXX this one should also be filled in */ cred->authdata = NULL; cred->addresses = calloc(incred->addresses.len + 1, sizeof(cred->addresses[0])); if (cred->addresses == NULL) { ret = ENOMEM; goto fail; } for (i = 0; i < incred->addresses.len; i++) { cc_data *addr; addr = malloc(sizeof(*addr)); if (addr == NULL) { ret = ENOMEM; goto fail; } addr->type = incred->addresses.val[i].addr_type; addr->length = incred->addresses.val[i].address.length; addr->data = malloc(addr->length); if (addr->data == NULL) { ret = ENOMEM; goto fail; } memcpy(addr->data, incred->addresses.val[i].address.data, addr->length); cred->addresses[i] = addr; } cred->addresses[i] = NULL; cred->ticket_flags = 0; if (incred->flags.b.forwardable) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDABLE; if (incred->flags.b.forwarded) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDED; if (incred->flags.b.proxiable) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXIABLE; if (incred->flags.b.proxy) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXY; if (incred->flags.b.may_postdate) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE; if (incred->flags.b.postdated) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_POSTDATED; if (incred->flags.b.invalid) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INVALID; if (incred->flags.b.renewable) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_RENEWABLE; if (incred->flags.b.initial) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INITIAL; if (incred->flags.b.pre_authent) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PRE_AUTH; if (incred->flags.b.hw_authent) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_HW_AUTH; if (incred->flags.b.transited_policy_checked) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED; if (incred->flags.b.ok_as_delegate) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE; if (incred->flags.b.anonymous) cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_ANONYMOUS; return 0;fail: free_ccred(cred); krb5_clear_error_string(context); return ret;}static cc_int32get_cc_name(krb5_acc *a){ cc_string_t name; cc_int32 error; error = (*a->ccache->func->get_name)(a->ccache, &name); if (error) return error; a->cache_name = strdup(name->data); (*name->func->release)(name); if (a->cache_name == NULL) return ccErrNoMem; return ccNoError;}static const char*acc_get_name(krb5_context context, krb5_ccache id){ krb5_acc *a = ACACHE(id); int32_t error; if (a->cache_name == NULL) { krb5_error_code ret; krb5_principal principal; char *name; ret = _krb5_get_default_principal_local(context, &principal); if (ret) return NULL; ret = krb5_unparse_name(context, principal, &name); krb5_free_principal(context, principal); if (ret) return NULL; error = (*a->context->func->create_new_ccache)(a->context, cc_credentials_v5, name, &a->ccache); krb5_xfree(name); if (error) return NULL; error = get_cc_name(a); if (error) return NULL; } return a->cache_name;}static krb5_error_codeacc_alloc(krb5_context context, krb5_ccache *id){ krb5_error_code ret; cc_int32 error; krb5_acc *a; ret = init_ccapi(context); if (ret) return ret; ret = krb5_data_alloc(&(*id)->data, sizeof(*a)); if (ret) { krb5_clear_error_string(context); return ret; } a = ACACHE(*id); error = (*init_func)(&a->context, ccapi_version_3, NULL, NULL); if (error) { krb5_data_free(&(*id)->data); return translate_cc_error(context, error); } a->cache_name = NULL; return 0;}static krb5_error_codeacc_resolve(krb5_context context, krb5_ccache *id, const char *res){ krb5_error_code ret; cc_int32 error; krb5_acc *a; ret = acc_alloc(context, id); if (ret) return ret; a = ACACHE(*id); error = (*a->context->func->open_ccache)(a->context, res, &a->ccache); if (error == ccNoError) { error = get_cc_name(a); if (error != ccNoError) { acc_close(context, *id); *id = NULL; return translate_cc_error(context, error); } } else if (error == ccErrCCacheNotFound) { a->ccache = NULL; a->cache_name = NULL; error = 0; } else { *id = NULL; return translate_cc_error(context, error); } return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -