/* * Request: * NameZ * Creds * * Response: * */ static krb5_error_code kcm_store_cred(krb5_context context, krb5_ccache id, krb5_creds *creds) { krb5_error_code ret; krb5_kcmcache *k = KCMCACHE(id); krb5_storage *request; ret = krb5_kcm_storage_request(context, KCM_OP_STORE, &request); if (ret) return ret; ret = krb5_store_stringz(request, k->name); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_store_creds(request, creds); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_kcm_call(context, request, NULL, NULL); krb5_storage_free(request); return ret; }
static krb5_error_code encode_creds(krb5_context context, krb5_creds *creds, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; sp = krb5_storage_emem(); if (sp == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } ret = krb5_store_creds(sp, creds); if (ret) { krb5_set_error_message(context, ret, N_("Failed to store credential in scache", "")); krb5_storage_free(sp); return ret; } ret = krb5_storage_to_data(sp, data); krb5_storage_free(sp); if (ret) krb5_set_error_message(context, ret, N_("Failed to encode credential in scache", "")); return ret; }
static krb5_error_code encode_creds(krb5_context context, krb5_creds *creds, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; krb5_data_zero(data); sp = krb5_storage_emem(); if (sp == NULL) return krb5_enomem(context); ret = krb5_store_creds(sp, creds); if (ret) { krb5_set_error_message(context, ret, N_("Failed to store credential in scache", "")); krb5_storage_free(sp); return ret; } ret = krb5_storage_to_data(sp, data); krb5_storage_free(sp); if (ret) krb5_set_error_message(context, ret, N_("Failed to encode credential in scache", "")); return ret; }
/* * Request: * NameZ * Cursor * * Response: * Creds */ static krb5_error_code kcm_op_get_next(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { krb5_error_code ret; kcm_ccache ccache; char *name; u_int32_t cursor; kcm_cursor *c; ret = krb5_ret_stringz(request, &name); if (ret) return ret; KCM_LOG_REQUEST_NAME(context, client, opcode, name); ret = krb5_ret_int32(request, &cursor); if (ret) { free(name); return ret; } ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache); if (ret) { free(name); return ret; } ret = kcm_cursor_find(context, client->pid, ccache, cursor, &c); if (ret) { kcm_release_ccache(context, &ccache); free(name); return ret; } HEIMDAL_MUTEX_lock(&ccache->mutex); if (c->credp == NULL) { ret = KRB5_CC_END; } else { ret = krb5_store_creds(response, &c->credp->cred); c->credp = c->credp->next; } HEIMDAL_MUTEX_unlock(&ccache->mutex); free(name); kcm_release_ccache(context, &ccache); return ret; }
/* * Request: * NameZ * Cursor * * Response: * Creds */ static krb5_error_code kcm_op_get_cred_by_uuid(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { krb5_error_code ret; kcm_ccache ccache; char *name; struct kcm_creds *c; kcmuuid_t uuid; ssize_t sret; ret = krb5_ret_stringz(request, &name); if (ret) return ret; KCM_LOG_REQUEST_NAME(context, client, opcode, name); ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache); free(name); if (ret) return ret; sret = krb5_storage_read(request, &uuid, sizeof(uuid)); if (sret != sizeof(uuid)) { kcm_release_ccache(context, ccache); krb5_clear_error_message(context); return KRB5_CC_IO; } c = kcm_ccache_find_cred_uuid(context, ccache, uuid); if (c == NULL) { kcm_release_ccache(context, ccache); return KRB5_CC_END; } HEIMDAL_MUTEX_lock(&ccache->mutex); ret = krb5_store_creds(response, &c->cred); HEIMDAL_MUTEX_unlock(&ccache->mutex); kcm_release_ccache(context, ccache); return ret; }
static krb5_error_code fcc_store_cred(krb5_context context, krb5_ccache id, krb5_creds *creds) { int ret; int fd; ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY | O_CLOEXEC, 0); if(ret) return ret; { krb5_storage *sp; sp = krb5_storage_emem(); krb5_storage_set_eof_code(sp, KRB5_CC_END); storage_set_flags(context, sp, FCACHE(id)->version); if (!krb5_config_get_bool_default(context, NULL, TRUE, "libdefaults", "fcc-mit-ticketflags", NULL)) krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER); ret = krb5_store_creds(sp, creds); if (ret == 0) ret = write_storage(context, sp, fd); krb5_storage_free(sp); } fcc_unlock(context, fd); if (close(fd) < 0) { if (ret == 0) { ret = errno; krb5_set_error_message (context, ret, N_("close %s: %s", ""), FILENAME(id), strerror(ret)); } } return ret; }
/* * Request: * NameZ * WhichFields * MatchCreds * * Response: * Creds * */ static krb5_error_code kcm_op_retrieve(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { uint32_t flags; krb5_creds mcreds; krb5_error_code ret; kcm_ccache ccache; char *name; krb5_creds *credp; int free_creds = 0; ret = krb5_ret_stringz(request, &name); if (ret) return ret; KCM_LOG_REQUEST_NAME(context, client, opcode, name); ret = krb5_ret_uint32(request, &flags); if (ret) { free(name); return ret; } ret = krb5_ret_creds_tag(request, &mcreds); if (ret) { free(name); return ret; } if (disallow_getting_krbtgt && mcreds.server->name.name_string.len == 2 && strcmp(mcreds.server->name.name_string.val[0], KRB5_TGS_NAME) == 0) { free(name); krb5_free_cred_contents(context, &mcreds); return KRB5_FCC_PERM; } ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache); if (ret) { free(name); krb5_free_cred_contents(context, &mcreds); return ret; } ret = kcm_ccache_retrieve_cred(context, ccache, flags, &mcreds, &credp); if (ret && ((flags & KRB5_GC_CACHED) == 0) && !krb5_is_config_principal(context, mcreds.server)) { krb5_ccache_data ccdata; /* try and acquire */ HEIMDAL_MUTEX_lock(&ccache->mutex); /* Fake up an internal ccache */ kcm_internal_ccache(context, ccache, &ccdata); /* glue cc layer will store creds */ ret = krb5_get_credentials(context, 0, &ccdata, &mcreds, &credp); if (ret == 0) free_creds = 1; HEIMDAL_MUTEX_unlock(&ccache->mutex); } if (ret == 0) { ret = krb5_store_creds(response, credp); } free(name); krb5_free_cred_contents(context, &mcreds); kcm_release_ccache(context, ccache); if (free_creds) krb5_free_cred_contents(context, credp); return ret; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_export_cred(OM_uint32 *minor_status, gss_cred_id_t cred_handle, gss_buffer_t cred_token) { gsskrb5_cred handle = (gsskrb5_cred)cred_handle; krb5_context context; krb5_error_code ret; krb5_storage *sp; krb5_data data, mech; char *str; GSSAPI_KRB5_INIT (&context); if (handle->usage != GSS_C_INITIATE && handle->usage != GSS_C_BOTH) { *minor_status = GSS_KRB5_S_G_BAD_USAGE; return GSS_S_FAILURE; } sp = krb5_storage_emem(); if (sp == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } /* type = krb5_cc_get_type(context, handle->ccache); * * XXX Always use reference keys since that makes it easier to * transport between processing in seprate authentication domain. * * We should encrypt credentials in KCM though using the kcm * session key. */ if (1 /*strcmp(type, "MEMORY") == 0 */) { krb5_creds *creds; ret = krb5_store_uint32(sp, 0); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = _krb5_get_krbtgt(context, handle->ccache, handle->principal->realm, &creds); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_store_creds(sp, creds); krb5_free_creds(context, creds); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } } else { ret = krb5_store_uint32(sp, 1); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_cc_get_full_name(context, handle->ccache, &str); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_store_string(sp, str); free(str); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } } ret = krb5_storage_to_data(sp, &data); krb5_storage_free(sp); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } sp = krb5_storage_emem(); if (sp == NULL) { krb5_data_free(&data); *minor_status = ENOMEM; return GSS_S_FAILURE; } mech.data = GSS_KRB5_MECHANISM->elements; mech.length = GSS_KRB5_MECHANISM->length; ret = krb5_store_data(sp, mech); if (ret) { krb5_data_free(&data); krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_store_data(sp, data); krb5_data_free(&data); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_storage_to_data(sp, &data); krb5_storage_free(sp); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } cred_token->value = data.data; cred_token->length = data.length; return GSS_S_COMPLETE; }
static krb5_error_code KRB5_CALLCONV xcc_store_cred(krb5_context context, krb5_ccache id, krb5_creds *creds) { krb5_xcc *x = XCACHE(id); krb5_storage *sp = NULL; CFDataRef dref = NULL; krb5_data data; CFStringRef principal = NULL; CFDictionaryRef query = NULL; krb5_error_code ret; CFBooleanRef is_tgt = kCFBooleanFalse; CFDateRef authtime = NULL; krb5_data_zero(&data); if (creds->times.starttime) { authtime = CFDateCreate(NULL, (CFTimeInterval)creds->times.starttime - kCFAbsoluteTimeIntervalSince1970); } else if (creds->times.authtime) { authtime = CFDateCreate(NULL, (CFTimeInterval)creds->times.authtime - kCFAbsoluteTimeIntervalSince1970); } else { authtime = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); } if (authtime == NULL) { ret = krb5_enomem(context); goto out; } sp = krb5_storage_emem(); if (sp == NULL) { ret = krb5_enomem(context); goto out; } ret = krb5_store_creds(sp, creds); if (ret) goto out; krb5_storage_to_data(sp, &data); dref = CFDataCreateWithBytesNoCopy(NULL, data.data, data.length, kCFAllocatorNull); if (dref == NULL) { ret = krb5_enomem(context); goto out; } if (krb5_principal_is_root_krbtgt(context, creds->server)) is_tgt = kCFBooleanTrue; principal = CFStringCreateFromPrincipal(context, creds->server); if (principal == NULL) { ret = krb5_enomem(context); goto out; } const void *add_keys[] = { (void *)kHEIMObjectType, kHEIMAttrType, kHEIMAttrClientName, kHEIMAttrServerName, kHEIMAttrData, kHEIMAttrParentCredential, kHEIMAttrLeadCredential, kHEIMAttrAuthTime, }; const void *add_values[] = { (void *)kHEIMObjectKerberos, kHEIMTypeKerberos, x->clientName, principal, dref, x->uuid, is_tgt, authtime, }; query = CFDictionaryCreate(NULL, add_keys, add_values, sizeof(add_keys) / sizeof(add_keys[0]), NULL, NULL); heim_assert(query != NULL, "Failed to create dictionary"); HeimCredRef ccred = HeimCredCreate(query, NULL); if (ccred) { CFRelease(ccred); } else { _krb5_debugx(context, 5, "failed to add credential to %s\n", x->cache_name); ret = EINVAL; krb5_set_error_message(context, ret, "failed to store credential to %s", x->cache_name); goto out; } out: if (sp) krb5_storage_free(sp); CFRELEASE_NULL(query); CFRELEASE_NULL(dref); CFRELEASE_NULL(principal); CFRELEASE_NULL(authtime); krb5_data_free(&data); return ret; }