/* * Allocate and initialise an IAKERB context */ static krb5_error_code iakerb_alloc_context(iakerb_ctx_id_t *pctx, int initiate) { iakerb_ctx_id_t ctx; krb5_error_code code; *pctx = NULL; ctx = k5alloc(sizeof(*ctx), &code); if (ctx == NULL) goto cleanup; ctx->defcred = GSS_C_NO_CREDENTIAL; ctx->magic = KG_IAKERB_CONTEXT; ctx->state = IAKERB_AS_REQ; ctx->count = 0; ctx->initiate = initiate; ctx->established = 0; code = krb5_gss_init_context(&ctx->k5c); if (code != 0) goto cleanup; *pctx = ctx; cleanup: if (code != 0) iakerb_release_context(ctx); return code; }
OM_uint32 KRB5_CALLCONV krb5_gss_release_any_name_mapping(OM_uint32 *minor_status, gss_name_t name, gss_buffer_t type_id, gss_any_t *input) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; char *kmodule; if (minor_status != NULL) *minor_status = 0; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (kname->ad_context == NULL) { code = krb5_authdata_context_init(context, &kname->ad_context); if (code != 0) { *minor_status = code; k5_mutex_unlock(&kname->lock); krb5_free_context(context); return GSS_S_UNAVAILABLE; } } kmodule = (char *)type_id->value; if (kmodule[type_id->length] != '\0') { k5_mutex_unlock(&kname->lock); krb5_free_context(context); return GSS_S_UNAVAILABLE; } code = krb5_authdata_free_internal(context, kname->ad_context, kmodule, *input); if (code == 0) *input = NULL; k5_mutex_unlock(&kname->lock); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
OM_uint32 KRB5_CALLCONV krb5_gss_set_name_attribute(OM_uint32 *minor_status, gss_name_t name, int complete, gss_buffer_t attr, gss_buffer_t value) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; krb5_data kattr; krb5_data kvalue; if (minor_status != NULL) *minor_status = 0; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (kname->ad_context == NULL) { code = krb5_authdata_context_init(context, &kname->ad_context); if (code != 0) { *minor_status = code; k5_mutex_unlock(&kname->lock); krb5_free_context(context); return GSS_S_UNAVAILABLE; } } kattr.data = (char *)attr->value; kattr.length = attr->length; kvalue.data = (char *)value->value; kvalue.length = value->length; code = krb5_authdata_set_attribute(context, kname->ad_context, complete, &kattr, &kvalue); k5_mutex_unlock(&kname->lock); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
OM_uint32 KRB5_CALLCONV krb5_gss_inquire_name(OM_uint32 *minor_status, gss_name_t name, int *name_is_MN, gss_OID *MN_mech, gss_buffer_set_t *attrs) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; krb5_data *kattrs = NULL; if (minor_status != NULL) *minor_status = 0; if (attrs != NULL) *attrs = GSS_C_NO_BUFFER_SET; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (kname->ad_context == NULL) { code = krb5_authdata_context_init(context, &kname->ad_context); if (code != 0) goto cleanup; } code = krb5_authdata_get_attribute_types(context, kname->ad_context, &kattrs); if (code != 0) goto cleanup; code = data_list_to_buffer_set(context, kattrs, attrs); kattrs = NULL; if (code != 0) goto cleanup; cleanup: k5_mutex_unlock(&kname->lock); krb5int_free_data_list(context, kattrs); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
OM_uint32 krb5_gss_delete_name_attribute(OM_uint32 *minor_status, gss_name_t name, gss_buffer_t attr) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; krb5_data kattr; if (minor_status != NULL) *minor_status = 0; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (!kg_validate_name(name)) { *minor_status = (OM_uint32)G_VALIDATE_FAILED; krb5_free_context(context); return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (kname->ad_context == NULL) { code = krb5_authdata_context_init(context, &kname->ad_context); if (code != 0) { *minor_status = code; k5_mutex_unlock(&kname->lock); krb5_free_context(context); return GSS_S_UNAVAILABLE; } } kattr.data = (char *)attr->value; kattr.length = attr->length; code = krb5_authdata_delete_attribute(context, kname->ad_context, &kattr); k5_mutex_unlock(&kname->lock); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
OM_uint32 KRB5_CALLCONV krb5_gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token, gss_cred_id_t *cred_handle) { OM_uint32 status = GSS_S_COMPLETE; krb5_context context; krb5_error_code ret; krb5_gss_cred_id_t cred; k5_json_value v = NULL; k5_json_array array; k5_json_string str; char *copy = NULL; ret = krb5_gss_init_context(&context); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } /* Decode token. */ copy = k5memdup0(token->value, token->length, &ret); if (copy == NULL) { status = GSS_S_FAILURE; *minor_status = ret; goto cleanup; } if (k5_json_decode(copy, &v)) goto invalid; /* Decode the CRED_EXPORT_MAGIC array wrapper. */ if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) goto invalid; array = v; if (k5_json_array_length(array) != 2) goto invalid; str = check_element(array, 0, K5_JSON_TID_STRING); if (str == NULL || strcmp(k5_json_string_utf8(str), CRED_EXPORT_MAGIC) != 0) goto invalid; if (json_to_kgcred(context, k5_json_array_get(array, 1), &cred)) goto invalid; *cred_handle = (gss_cred_id_t)cred; cleanup: free(copy); k5_json_release(v); krb5_free_context(context); return status; invalid: status = GSS_S_DEFECTIVE_TOKEN; goto cleanup; }
OM_uint32 krb5_gss_duplicate_name(OM_uint32 *minor_status, const gss_name_t input_name, gss_name_t *dest_name) { krb5_context context; krb5_error_code code; krb5_gss_name_t princ, outprinc; if (minor_status) *minor_status = 0; code = krb5_gss_init_context(&context); if (code) { if (minor_status) *minor_status = code; return GSS_S_FAILURE; } if (! kg_validate_name(input_name)) { if (minor_status) *minor_status = (OM_uint32) G_VALIDATE_FAILED; krb5_free_context(context); return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME); } princ = (krb5_gss_name_t)input_name; if ((code = kg_duplicate_name(context, princ, KG_INIT_NAME_INTERN, &outprinc))) { *minor_status = code; save_error_info(*minor_status, context); krb5_free_context(context); return(GSS_S_FAILURE); } krb5_free_context(context); *dest_name = (gss_name_t) outprinc; assert(kg_validate_name(*dest_name)); return(GSS_S_COMPLETE); }
OM_uint32 krb5_gss_export_name(OM_uint32 *minor_status, const gss_name_t input_name, gss_buffer_t exported_name) { krb5_context context; krb5_error_code code; size_t length; char *str; unsigned char *cp; if (minor_status) *minor_status = 0; code = krb5_gss_init_context(&context); if (code) { if (minor_status) *minor_status = code; return GSS_S_FAILURE; } exported_name->length = 0; exported_name->value = NULL; if (! kg_validate_name(input_name)) { if (minor_status) *minor_status = (OM_uint32) G_VALIDATE_FAILED; krb5_free_context(context); return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME); } if ((code = krb5_unparse_name(context, (krb5_principal) input_name, &str))) { if (minor_status) *minor_status = code; save_error_info((OM_uint32)code, context); krb5_free_context(context); return(GSS_S_FAILURE); } krb5_free_context(context); length = strlen(str); exported_name->length = 10 + length + gss_mech_krb5->length; exported_name->value = malloc(exported_name->length); if (!exported_name->value) { free(str); if (minor_status) *minor_status = ENOMEM; return(GSS_S_FAILURE); } cp = exported_name->value; /* Note: we assume the OID will be less than 128 bytes... */ *cp++ = 0x04; *cp++ = 0x01; store_16_be(gss_mech_krb5->length+2, cp); cp += 2; *cp++ = 0x06; *cp++ = (gss_mech_krb5->length) & 0xFF; memcpy(cp, gss_mech_krb5->elements, gss_mech_krb5->length); cp += gss_mech_krb5->length; store_32_be(length, cp); cp += 4; memcpy(cp, str, length); free(str); return(GSS_S_COMPLETE); }
/* The mechglue always passes null desired_mechs and actual_mechs. */ OM_uint32 KRB5_CALLCONV krb5_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status, const gss_cred_id_t impersonator_cred_handle, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gss_cred_id_t *output_cred_handle, gss_OID_set *actual_mechs, OM_uint32 *time_rec) { OM_uint32 major_status; krb5_error_code code; krb5_gss_cred_id_t cred; krb5_context context; if (impersonator_cred_handle == GSS_C_NO_CREDENTIAL) return GSS_S_CALL_INACCESSIBLE_READ; if (desired_name == GSS_C_NO_NAME) return GSS_S_CALL_INACCESSIBLE_READ; if (output_cred_handle == NULL) return GSS_S_CALL_INACCESSIBLE_WRITE; if (cred_usage != GSS_C_INITIATE) { *minor_status = (OM_uint32)G_BAD_USAGE; return GSS_S_FAILURE; } *output_cred_handle = GSS_C_NO_CREDENTIAL; if (time_rec != NULL) *time_rec = 0; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } major_status = kg_cred_resolve(minor_status, context, impersonator_cred_handle, NULL); if (GSS_ERROR(major_status)) { krb5_free_context(context); return major_status; } major_status = kg_impersonate_name(minor_status, (krb5_gss_cred_id_t)impersonator_cred_handle, (krb5_gss_name_t)desired_name, time_req, &cred, time_rec, context); if (!GSS_ERROR(major_status)) *output_cred_handle = (gss_cred_id_t)cred; k5_mutex_unlock(&((krb5_gss_cred_id_t)impersonator_cred_handle)->lock); krb5_free_context(context); return major_status; }
OM_uint32 KRB5_CALLCONV gss_krb5int_copy_ccache(OM_uint32 *minor_status, gss_cred_id_t cred_handle, const gss_OID desired_object, const gss_buffer_t value) { krb5_gss_cred_id_t k5creds; krb5_cc_cursor cursor; krb5_creds creds; krb5_error_code code; krb5_context context; krb5_ccache out_ccache; assert(value->length == sizeof(out_ccache)); if (value->length != sizeof(out_ccache)) return GSS_S_FAILURE; out_ccache = (krb5_ccache)value->value; /* cred handle will have been validated by gssspi_set_cred_option() */ k5creds = (krb5_gss_cred_id_t) cred_handle; code = k5_mutex_lock(&k5creds->lock); if (code) { *minor_status = code; return GSS_S_FAILURE; } if (k5creds->usage == GSS_C_ACCEPT) { k5_mutex_unlock(&k5creds->lock); *minor_status = (OM_uint32) G_BAD_USAGE; return(GSS_S_FAILURE); } code = krb5_gss_init_context(&context); if (code) { k5_mutex_unlock(&k5creds->lock); *minor_status = code; return GSS_S_FAILURE; } code = krb5_cc_start_seq_get(context, k5creds->ccache, &cursor); if (code) { k5_mutex_unlock(&k5creds->lock); *minor_status = code; save_error_info(*minor_status, context); krb5_free_context(context); return(GSS_S_FAILURE); } while (!code && !krb5_cc_next_cred(context, k5creds->ccache, &cursor, &creds)) { code = krb5_cc_store_cred(context, out_ccache, &creds); krb5_free_cred_contents(context, &creds); } krb5_cc_end_seq_get(context, k5creds->ccache, &cursor); k5_mutex_unlock(&k5creds->lock); *minor_status = code; if (code) save_error_info(*minor_status, context); krb5_free_context(context); return code ? GSS_S_FAILURE : GSS_S_COMPLETE; }
OM_uint32 KRB5_CALLCONV krb5_gss_export_name_composite(OM_uint32 *minor_status, gss_name_t name, gss_buffer_t exp_composite_name) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; krb5_data *attrs = NULL; char *princstr = NULL; unsigned char *cp; size_t princlen; if (minor_status != NULL) *minor_status = 0; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } code = krb5_unparse_name(context, kname->princ, &princstr); if (code != 0) goto cleanup; princlen = strlen(princstr); if (kname->ad_context != NULL) { code = krb5_authdata_export_attributes(context, kname->ad_context, AD_USAGE_MASK, &attrs); if (code != 0) goto cleanup; } /* 04 02 OID Name AuthData */ exp_composite_name->length = 10 + gss_mech_krb5->length + princlen; if (attrs != NULL) exp_composite_name->length += 4 + attrs->length; exp_composite_name->value = malloc(exp_composite_name->length); if (exp_composite_name->value == NULL) { code = ENOMEM; goto cleanup; } cp = exp_composite_name->value; /* Note: we assume the OID will be less than 128 bytes... */ *cp++ = 0x04; if (attrs != NULL) *cp++ = 0x02; else *cp++ = 0x01; store_16_be(gss_mech_krb5->length + 2, cp); cp += 2; *cp++ = 0x06; *cp++ = (gss_mech_krb5->length) & 0xFF; memcpy(cp, gss_mech_krb5->elements, gss_mech_krb5->length); cp += gss_mech_krb5->length; store_32_be(princlen, cp); cp += 4; memcpy(cp, princstr, princlen); cp += princlen; if (attrs != NULL) { store_32_be(attrs->length, cp); cp += 4; memcpy(cp, attrs->data, attrs->length); cp += attrs->length; } cleanup: krb5_free_unparsed_name(context, princstr); krb5_free_data(context, attrs); k5_mutex_unlock(&kname->lock); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
OM_uint32 KRB5_CALLCONV krb5_gss_get_name_attribute(OM_uint32 *minor_status, gss_name_t name, gss_buffer_t attr, int *authenticated, int *complete, gss_buffer_t value, gss_buffer_t display_value, int *more) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; krb5_data kattr; krb5_boolean kauthenticated; krb5_boolean kcomplete; krb5_data kvalue; krb5_data kdisplay_value; if (minor_status != NULL) *minor_status = 0; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; krb5_free_context(context); return GSS_S_FAILURE; } if (kname->ad_context == NULL) { code = krb5_authdata_context_init(context, &kname->ad_context); if (code != 0) { *minor_status = code; k5_mutex_unlock(&kname->lock); krb5_free_context(context); return GSS_S_UNAVAILABLE; } } kattr.data = (char *)attr->value; kattr.length = attr->length; kauthenticated = FALSE; kcomplete = FALSE; code = krb5_authdata_get_attribute(context, kname->ad_context, &kattr, &kauthenticated, &kcomplete, value ? &kvalue : NULL, display_value ? &kdisplay_value : NULL, more); if (code == 0) { if (value != NULL) code = data_to_gss(&kvalue, value); if (authenticated != NULL) *authenticated = kauthenticated; if (complete != NULL) *complete = kcomplete; if (display_value != NULL) { if (code == 0) code = data_to_gss(&kdisplay_value, display_value); else free(kdisplay_value.data); } } k5_mutex_unlock(&kname->lock); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
OM_uint32 krb5_gss_map_name_to_any(OM_uint32 *minor_status, gss_name_t name, int authenticated, gss_buffer_t type_id, gss_any_t *output) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; char *kmodule; if (minor_status != NULL) *minor_status = 0; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (!kg_validate_name(name)) { *minor_status = (OM_uint32)G_VALIDATE_FAILED; krb5_free_context(context); return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (kname->ad_context == NULL) { code = krb5_authdata_context_init(context, &kname->ad_context); if (code != 0) { *minor_status = code; k5_mutex_unlock(&kname->lock); krb5_free_context(context); return GSS_S_UNAVAILABLE; } } kmodule = (char *)type_id->value; if (kmodule[type_id->length] != '\0') { k5_mutex_unlock(&kname->lock); krb5_free_context(context); return GSS_S_UNAVAILABLE; } code = krb5_authdata_export_internal(context, kname->ad_context, authenticated, kmodule, (void **)output); k5_mutex_unlock(&kname->lock); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
OM_uint32 krb5_gss_get_name_attribute(OM_uint32 *minor_status, gss_name_t name, gss_buffer_t attr, int *authenticated, int *complete, gss_buffer_t value, gss_buffer_t display_value, int *more) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; krb5_data kattr; krb5_boolean kauthenticated; krb5_boolean kcomplete; krb5_data kvalue; krb5_data kdisplay_value; if (minor_status != NULL) *minor_status = 0; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (!kg_validate_name(name)) { *minor_status = (OM_uint32)G_VALIDATE_FAILED; krb5_free_context(context); return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; krb5_free_context(context); return GSS_S_FAILURE; } if (kname->ad_context == NULL) { code = krb5_authdata_context_init(context, &kname->ad_context); if (code != 0) { *minor_status = code; k5_mutex_unlock(&kname->lock); krb5_free_context(context); return GSS_S_UNAVAILABLE; } } kattr.data = (char *)attr->value; kattr.length = attr->length; kauthenticated = FALSE; kcomplete = FALSE; code = krb5_authdata_get_attribute(context, kname->ad_context, &kattr, &kauthenticated, &kcomplete, value ? &kvalue : NULL, display_value ? &kdisplay_value : NULL, more); if (code == 0) { if (value != NULL) { value->value = kvalue.data; value->length = kvalue.length; } if (authenticated != NULL) *authenticated = kauthenticated; if (complete != NULL) *complete = kcomplete; if (display_value != NULL) { display_value->value = kdisplay_value.data; display_value->length = kdisplay_value.length; } } k5_mutex_unlock(&kname->lock); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
static OM_uint32 copy_initiator_creds(OM_uint32 *minor_status, gss_cred_id_t input_cred_handle, const gss_OID desired_mech, OM_uint32 overwrite_cred, OM_uint32 default_cred) { OM_uint32 major_status; krb5_error_code code; krb5_gss_cred_id_t kcred = NULL; krb5_context context = NULL; krb5_ccache ccache = NULL; if (!default_cred) { *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP; major_status = GSS_S_FAILURE; goto cleanup; } code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } major_status = krb5_gss_validate_cred_1(minor_status, input_cred_handle, context); if (GSS_ERROR(major_status)) goto cleanup; kcred = (krb5_gss_cred_id_t)input_cred_handle; if (kcred->ccache == NULL || kcred->proxy_cred) { *minor_status = KG_CCACHE_NOMATCH; major_status = GSS_S_DEFECTIVE_CREDENTIAL; goto cleanup; } if (!overwrite_cred && has_unexpired_creds(kcred, desired_mech, default_cred)) { major_status = GSS_S_DUPLICATE_ELEMENT; goto cleanup; } code = krb5int_cc_default(context, &ccache); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } code = krb5_cc_copy_creds(context, kcred->ccache, ccache); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } *minor_status = 0; major_status = GSS_S_COMPLETE; cleanup: if (kcred != NULL) k5_mutex_unlock(&kcred->lock); if (ccache != NULL) krb5_cc_close(context, ccache); krb5_free_context(context); return major_status; }
static OM_uint32 copy_initiator_creds(OM_uint32 *minor_status, gss_cred_id_t input_cred_handle, const gss_OID desired_mech, OM_uint32 overwrite_cred, OM_uint32 default_cred, gss_const_key_value_set_t cred_store) { OM_uint32 major_status; krb5_error_code code; krb5_gss_cred_id_t kcred = NULL; krb5_context context = NULL; krb5_ccache ccache = NULL; const char *ccache_name; *minor_status = 0; if (!default_cred && cred_store == GSS_C_NO_CRED_STORE) { *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP; major_status = GSS_S_FAILURE; goto cleanup; } code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } major_status = krb5_gss_validate_cred_1(minor_status, input_cred_handle, context); if (GSS_ERROR(major_status)) goto cleanup; kcred = (krb5_gss_cred_id_t)input_cred_handle; if (kcred->ccache == NULL) { *minor_status = KG_CCACHE_NOMATCH; major_status = GSS_S_DEFECTIVE_CREDENTIAL; goto cleanup; } if (!overwrite_cred && has_unexpired_creds(kcred, desired_mech, default_cred, cred_store)) { major_status = GSS_S_DUPLICATE_ELEMENT; goto cleanup; } major_status = kg_value_from_cred_store(cred_store, KRB5_CS_CCACHE_URN, &ccache_name); if (GSS_ERROR(major_status)) goto cleanup; if (ccache_name != NULL) { code = krb5_cc_resolve(context, ccache_name, &ccache); if (code != 0) { *minor_status = code; major_status = GSS_S_CRED_UNAVAIL; goto cleanup; } code = krb5_cc_initialize(context, ccache, kcred->name->princ); if (code != 0) { *minor_status = code; major_status = GSS_S_CRED_UNAVAIL; goto cleanup; } } if (ccache == NULL) { if (!default_cred) { *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP; major_status = GSS_S_FAILURE; goto cleanup; } code = krb5int_cc_default(context, &ccache); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } } code = krb5_cc_copy_creds(context, kcred->ccache, ccache); if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; goto cleanup; } *minor_status = 0; major_status = GSS_S_COMPLETE; cleanup: if (kcred != NULL) k5_mutex_unlock(&kcred->lock); if (ccache != NULL) krb5_cc_close(context, ccache); krb5_free_context(context); return major_status; }