krb5_error_code kg_init_name(krb5_context context, krb5_principal principal, krb5_authdata_context ad_context, krb5_flags flags, krb5_gss_name_t *ret_name) { krb5_error_code code; krb5_gss_name_t name; *ret_name = NULL; assert(principal != NULL); if (principal == NULL) return EINVAL; name = xmalloc(sizeof(krb5_gss_name_rec)); if (name == NULL) return ENOMEM; memset(name, 0, sizeof(krb5_gss_name_rec)); code = k5_mutex_init(&name->lock); if (code != 0) goto cleanup; if ((flags & KG_INIT_NAME_NO_COPY) == 0) { code = krb5_copy_principal(context, principal, &name->princ); if (code != 0) goto cleanup; if (ad_context != NULL) { code = krb5_authdata_context_copy(context, ad_context, &name->ad_context); if (code != 0) goto cleanup; } } else { name->princ = principal; name->ad_context = ad_context; } if ((flags & KG_INIT_NAME_INTERN) && !kg_save_name((gss_name_t)name)) { code = G_VALIDATE_FAILED; goto cleanup; } *ret_name = name; cleanup: if (code != 0) kg_release_name(context, 0, &name); return code; }
/* Convert a JSON value to a krb5 GSS name or to NULL. */ static int json_to_kgname(krb5_context context, k5_json_value v, krb5_gss_name_t *name_out) { k5_json_array array; krb5_gss_name_t name = NULL; *name_out = NULL; if (k5_json_get_tid(v) == K5_JSON_TID_NULL) return 0; if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) return -1; array = v; if (k5_json_array_length(array) != 3) return -1; name = calloc(1, sizeof(*name)); if (name == NULL) return -1; if (k5_mutex_init(&name->lock)) { free(name); return -1; } if (json_to_principal(context, k5_json_array_get(array, 0), &name->princ)) goto invalid; if (json_to_optional_string(k5_json_array_get(array, 1), &name->service)) goto invalid; if (json_to_optional_string(k5_json_array_get(array, 2), &name->host)) goto invalid; *name_out = name; return 0; invalid: kg_release_name(context, &name); return -1; }
OM_uint32 kg_compose_deleg_cred(OM_uint32 *minor_status, krb5_gss_cred_id_t impersonator_cred, krb5_creds *subject_creds, OM_uint32 time_req, krb5_gss_cred_id_t *output_cred, OM_uint32 *time_rec, krb5_context context) { OM_uint32 major_status; krb5_error_code code; krb5_gss_cred_id_t cred = NULL; *output_cred = NULL; k5_mutex_assert_locked(&impersonator_cred->lock); if (!kg_is_initiator_cred(impersonator_cred) || impersonator_cred->name == NULL || impersonator_cred->impersonator != NULL) { code = G_BAD_USAGE; goto cleanup; } assert(impersonator_cred->name->princ != NULL); assert(subject_creds != NULL); assert(subject_creds->client != NULL); cred = xmalloc(sizeof(*cred)); if (cred == NULL) { code = ENOMEM; goto cleanup; } memset(cred, 0, sizeof(*cred)); code = k5_mutex_init(&cred->lock); if (code != 0) goto cleanup; cred->usage = GSS_C_INITIATE; cred->tgt_expire = subject_creds->times.endtime; code = kg_init_name(context, subject_creds->client, NULL, NULL, NULL, 0, &cred->name); if (code != 0) goto cleanup; code = krb5_cc_new_unique(context, "MEMORY", NULL, &cred->ccache); if (code != 0) goto cleanup; cred->destroy_ccache = 1; code = krb5_cc_initialize(context, cred->ccache, subject_creds->client); if (code != 0) goto cleanup; /* * Only return a "proxy" credential for use with constrained * delegation if the subject credentials are forwardable. * Submitting non-forwardable credentials to the KDC for use * with constrained delegation will only return an error. */ if (subject_creds->ticket_flags & TKT_FLG_FORWARDABLE) { code = make_proxy_cred(context, cred, impersonator_cred); if (code != 0) goto cleanup; } code = krb5_cc_store_cred(context, cred->ccache, subject_creds); if (code != 0) goto cleanup; if (time_rec != NULL) { krb5_timestamp now; code = krb5_timeofday(context, &now); if (code != 0) goto cleanup; *time_rec = cred->tgt_expire - now; } major_status = GSS_S_COMPLETE; *minor_status = 0; *output_cred = cred; cleanup: if (code != 0) { *minor_status = code; major_status = GSS_S_FAILURE; } if (GSS_ERROR(major_status) && cred != NULL) { k5_mutex_destroy(&cred->lock); krb5_cc_destroy(context, cred->ccache); kg_release_name(context, &cred->name); xfree(cred); } return major_status; }
krb5_error_code kg_init_name(krb5_context context, krb5_principal principal, char *service, char *host, krb5_authdata_context ad_context, krb5_flags flags, krb5_gss_name_t *ret_name) { krb5_error_code code; krb5_gss_name_t name; *ret_name = NULL; assert(principal != NULL); if (principal == NULL) return EINVAL; name = xmalloc(sizeof(krb5_gss_name_rec)); if (name == NULL) return ENOMEM; memset(name, 0, sizeof(krb5_gss_name_rec)); code = k5_mutex_init(&name->lock); if (code != 0) goto cleanup; if ((flags & KG_INIT_NAME_NO_COPY) == 0) { code = krb5_copy_principal(context, principal, &name->princ); if (code != 0) goto cleanup; if (ad_context != NULL) { code = krb5_authdata_context_copy(context, ad_context, &name->ad_context); if (code != 0) goto cleanup; } code = ENOMEM; if (service != NULL) { name->service = strdup(service); if (name->service == NULL) goto cleanup; } if (host != NULL) { name->host = strdup(host); if (name->host == NULL) goto cleanup; } code = 0; } else { name->princ = principal; name->service = service; name->host = host; name->ad_context = ad_context; } *ret_name = name; cleanup: if (code != 0) kg_release_name(context, &name); return code; }